-- Territory Manager System Schema
-- This migration creates the core tables for the Territory Manager system

-- Create territories table
CREATE TABLE IF NOT EXISTS territories (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    boundary JSONB, -- GeoJSON polygon for territory bounds
    population INTEGER,
    market_size VARCHAR(50),
    assigned_to UUID REFERENCES users(id),
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create territory_managers table
CREATE TABLE IF NOT EXISTS territory_managers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES users(id) UNIQUE NOT NULL,
    territory_id UUID REFERENCES territories(id),
    referral_code VARCHAR(50) UNIQUE NOT NULL,
    status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'active', 'suspended', 'inactive')),
    application_date TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    approved_date TIMESTAMP WITH TIME ZONE,
    approved_by UUID REFERENCES users(id),
    profile JSONB, -- Personal info, preferences, etc.
    documents JSONB, -- Uploaded documents like ID, W-9, etc.
    earnings_data JSONB, -- Earnings statistics and history
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create territory_applications table
CREATE TABLE IF NOT EXISTS territory_applications (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) NOT NULL,
    full_name VARCHAR(255) NOT NULL,
    phone VARCHAR(20),
    address JSONB, -- Address information
    desired_territory VARCHAR(255),
    has_transportation BOOLEAN DEFAULT false,
    has_event_experience BOOLEAN DEFAULT false,
    motivation TEXT,
    documents JSONB, -- File uploads
    consent JSONB, -- Background check and data processing consent
    status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'rejected')),
    reviewed_by UUID REFERENCES users(id),
    reviewed_at TIMESTAMP WITH TIME ZONE,
    review_notes TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create leads table
CREATE TABLE IF NOT EXISTS leads (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    territory_manager_id UUID REFERENCES territory_managers(id) NOT NULL,
    event_name VARCHAR(255) NOT NULL,
    organizer_contact JSONB, -- Contact information
    event_details JSONB, -- Event details like date, type, etc.
    status VARCHAR(20) DEFAULT 'cold' CHECK (status IN ('cold', 'contacted', 'confirmed', 'converted', 'dead')),
    notes TEXT[],
    follow_up_date TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create commissions table
CREATE TABLE IF NOT EXISTS commissions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    territory_manager_id UUID REFERENCES territory_managers(id) NOT NULL,
    event_id UUID REFERENCES events(id) NOT NULL,
    tickets_sold INTEGER DEFAULT 0,
    commission_per_ticket DECIMAL(10,2) DEFAULT 0.10,
    total_commission DECIMAL(10,2) DEFAULT 0,
    status VARCHAR(20) DEFAULT 'unpaid' CHECK (status IN ('unpaid', 'paid', 'pending')),
    payout_date TIMESTAMP WITH TIME ZONE,
    stripe_transfer_id VARCHAR(255),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create training_progress table
CREATE TABLE IF NOT EXISTS training_progress (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    territory_manager_id UUID REFERENCES territory_managers(id) NOT NULL,
    module_id VARCHAR(255) NOT NULL,
    completed_at TIMESTAMP WITH TIME ZONE,
    score INTEGER,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(territory_manager_id, module_id)
);

-- Create achievements table
CREATE TABLE IF NOT EXISTS achievements (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    description TEXT,
    requirements JSONB, -- Achievement requirements
    reward_amount DECIMAL(10,2) DEFAULT 0,
    badge_icon VARCHAR(255),
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create territory_manager_achievements table
CREATE TABLE IF NOT EXISTS territory_manager_achievements (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    territory_manager_id UUID REFERENCES territory_managers(id) NOT NULL,
    achievement_id UUID REFERENCES achievements(id) NOT NULL,
    earned_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(territory_manager_id, achievement_id)
);

-- Create expense_reports table
CREATE TABLE IF NOT EXISTS expense_reports (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    territory_manager_id UUID REFERENCES territory_managers(id) NOT NULL,
    event_id UUID REFERENCES events(id),
    mileage DECIMAL(10,2) DEFAULT 0,
    receipts JSONB, -- File uploads
    total_amount DECIMAL(10,2) DEFAULT 0,
    status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'paid', 'rejected')),
    submitted_date TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    approved_date TIMESTAMP WITH TIME ZONE,
    approved_by UUID REFERENCES users(id),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create notifications table
CREATE TABLE IF NOT EXISTS tm_notifications (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    territory_manager_id UUID REFERENCES territory_managers(id) NOT NULL,
    type VARCHAR(50) NOT NULL,
    title VARCHAR(255) NOT NULL,
    message TEXT,
    data JSONB, -- Additional notification data
    read BOOLEAN DEFAULT false,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create indexes for better performance
CREATE INDEX idx_territories_assigned_to ON territories(assigned_to);
CREATE INDEX idx_territory_managers_user_id ON territory_managers(user_id);
CREATE INDEX idx_territory_managers_territory_id ON territory_managers(territory_id);
CREATE INDEX idx_territory_managers_status ON territory_managers(status);
CREATE INDEX idx_territory_applications_status ON territory_applications(status);
CREATE INDEX idx_territory_applications_email ON territory_applications(email);
CREATE INDEX idx_leads_territory_manager_id ON leads(territory_manager_id);
CREATE INDEX idx_leads_status ON leads(status);
CREATE INDEX idx_commissions_territory_manager_id ON commissions(territory_manager_id);
CREATE INDEX idx_commissions_event_id ON commissions(event_id);
CREATE INDEX idx_commissions_status ON commissions(status);
CREATE INDEX idx_training_progress_territory_manager_id ON training_progress(territory_manager_id);
CREATE INDEX idx_tm_notifications_territory_manager_id ON tm_notifications(territory_manager_id);
CREATE INDEX idx_tm_notifications_read ON tm_notifications(read);

-- Add RLS policies
ALTER TABLE territories ENABLE ROW LEVEL SECURITY;
ALTER TABLE territory_managers ENABLE ROW LEVEL SECURITY;
ALTER TABLE territory_applications ENABLE ROW LEVEL SECURITY;
ALTER TABLE leads ENABLE ROW LEVEL SECURITY;
ALTER TABLE commissions ENABLE ROW LEVEL SECURITY;
ALTER TABLE training_progress ENABLE ROW LEVEL SECURITY;
ALTER TABLE achievements ENABLE ROW LEVEL SECURITY;
ALTER TABLE territory_manager_achievements ENABLE ROW LEVEL SECURITY;
ALTER TABLE expense_reports ENABLE ROW LEVEL SECURITY;
ALTER TABLE tm_notifications ENABLE ROW LEVEL SECURITY;

-- Basic RLS policies (admin can see all, territory managers can only see their own data)
CREATE POLICY "Admin can view all territories" ON territories FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can view their territory" ON territories FOR SELECT USING (assigned_to = auth.uid());

CREATE POLICY "Admin can view all territory managers" ON territory_managers FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can view their own data" ON territory_managers FOR SELECT USING (user_id = auth.uid());
CREATE POLICY "Territory managers can update their own data" ON territory_managers FOR UPDATE USING (user_id = auth.uid());

CREATE POLICY "Admin can view all applications" ON territory_applications FOR ALL USING (is_admin());
CREATE POLICY "Public can create applications" ON territory_applications FOR INSERT WITH CHECK (true);

CREATE POLICY "Admin can view all leads" ON leads FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can manage their leads" ON leads FOR ALL USING (
    EXISTS (SELECT 1 FROM territory_managers WHERE territory_managers.id = leads.territory_manager_id AND territory_managers.user_id = auth.uid())
);

CREATE POLICY "Admin can view all commissions" ON commissions FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can view their commissions" ON commissions FOR SELECT USING (
    EXISTS (SELECT 1 FROM territory_managers WHERE territory_managers.id = commissions.territory_manager_id AND territory_managers.user_id = auth.uid())
);

CREATE POLICY "Admin can view all training progress" ON training_progress FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can manage their training progress" ON training_progress FOR ALL USING (
    EXISTS (SELECT 1 FROM territory_managers WHERE territory_managers.id = training_progress.territory_manager_id AND territory_managers.user_id = auth.uid())
);

CREATE POLICY "Everyone can view achievements" ON achievements FOR SELECT USING (true);
CREATE POLICY "Admin can manage achievements" ON achievements FOR ALL USING (is_admin());

CREATE POLICY "Admin can view all territory manager achievements" ON territory_manager_achievements FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can view their achievements" ON territory_manager_achievements FOR SELECT USING (
    EXISTS (SELECT 1 FROM territory_managers WHERE territory_managers.id = territory_manager_achievements.territory_manager_id AND territory_managers.user_id = auth.uid())
);

CREATE POLICY "Admin can view all expense reports" ON expense_reports FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can manage their expense reports" ON expense_reports FOR ALL USING (
    EXISTS (SELECT 1 FROM territory_managers WHERE territory_managers.id = expense_reports.territory_manager_id AND territory_managers.user_id = auth.uid())
);

CREATE POLICY "Admin can view all notifications" ON tm_notifications FOR ALL USING (is_admin());
CREATE POLICY "Territory managers can view their notifications" ON tm_notifications FOR SELECT USING (
    EXISTS (SELECT 1 FROM territory_managers WHERE territory_managers.id = tm_notifications.territory_manager_id AND territory_managers.user_id = auth.uid())
);
CREATE POLICY "Territory managers can update their notifications" ON tm_notifications FOR UPDATE USING (
    EXISTS (SELECT 1 FROM territory_managers WHERE territory_managers.id = tm_notifications.territory_manager_id AND territory_managers.user_id = auth.uid())
);

-- Create trigger for updating updated_at timestamps
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_territories_updated_at BEFORE UPDATE ON territories
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_territory_managers_updated_at BEFORE UPDATE ON territory_managers
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_territory_applications_updated_at BEFORE UPDATE ON territory_applications
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_leads_updated_at BEFORE UPDATE ON leads
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_commissions_updated_at BEFORE UPDATE ON commissions
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_expense_reports_updated_at BEFORE UPDATE ON expense_reports
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- Function to generate unique referral codes
CREATE OR REPLACE FUNCTION generate_referral_code() RETURNS TEXT AS $$
DECLARE
    code TEXT;
    exists_check INTEGER;
BEGIN
    LOOP
        code := UPPER(SUBSTRING(MD5(random()::text) FROM 1 FOR 8));
        SELECT COUNT(*) INTO exists_check FROM territory_managers WHERE referral_code = code;
        IF exists_check = 0 THEN
            RETURN code;
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Function to auto-assign referral code when creating territory manager
CREATE OR REPLACE FUNCTION auto_assign_referral_code() RETURNS TRIGGER AS $$
BEGIN
    IF NEW.referral_code IS NULL OR NEW.referral_code = '' THEN
        NEW.referral_code := generate_referral_code();
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER auto_assign_referral_code_trigger
    BEFORE INSERT ON territory_managers
    FOR EACH ROW
    EXECUTE FUNCTION auto_assign_referral_code();

-- Function to calculate commission totals
CREATE OR REPLACE FUNCTION calculate_commission_total() RETURNS TRIGGER AS $$
BEGIN
    NEW.total_commission := NEW.tickets_sold * NEW.commission_per_ticket;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER calculate_commission_total_trigger
    BEFORE INSERT OR UPDATE ON commissions
    FOR EACH ROW
    EXECUTE FUNCTION calculate_commission_total();

-- Insert sample achievements
INSERT INTO achievements (name, description, requirements, reward_amount, badge_icon) VALUES
('First Referral', 'Successfully refer your first event to BCT', '{"referrals": 1}', 50.00, 'first-referral.svg'),
('Sales Champion', 'Refer 10 events in a single month', '{"monthly_referrals": 10}', 500.00, 'sales-champion.svg'),
('Territory Master', 'Maintain 95% event success rate for 3 months', '{"success_rate": 0.95, "months": 3}', 1000.00, 'territory-master.svg'),
('Training Graduate', 'Complete all training modules', '{"training_modules": "all"}', 100.00, 'training-graduate.svg'),
('Community Builder', 'Refer 5 recurring events', '{"recurring_events": 5}', 300.00, 'community-builder.svg'),
('Revenue Generator', 'Generate over $10,000 in commission in a quarter', '{"quarterly_commission": 10000}', 2000.00, 'revenue-generator.svg');