import { query, queryOne } from '../../config/database.js';
import { NotFoundError, ConflictError } from '../../shared/errors/index.js';

export interface SalesTeamMember {
  id: string;
  sales_team_id: string;
  user_id: string;
  user_name?: string;
  user_email?: string;
  role?: string;
  joined_at: Date;
}

export interface SalesTeam {
  id: string;
  tenant_id: string;
  company_id: string;
  company_name?: string;
  name: string;
  code?: string;
  team_leader_id?: string;
  team_leader_name?: string;
  target_monthly?: number;
  target_annual?: number;
  active: boolean;
  members?: SalesTeamMember[];
  created_at: Date;
}

export interface CreateSalesTeamDto {
  company_id: string;
  name: string;
  code?: string;
  team_leader_id?: string;
  target_monthly?: number;
  target_annual?: number;
}

export interface UpdateSalesTeamDto {
  name?: string;
  code?: string;
  team_leader_id?: string | null;
  target_monthly?: number | null;
  target_annual?: number | null;
  active?: boolean;
}

export interface SalesTeamFilters {
  company_id?: string;
  active?: boolean;
  page?: number;
  limit?: number;
}

class SalesTeamsService {
  async findAll(tenantId: string, filters: SalesTeamFilters = {}): Promise<{ data: SalesTeam[]; total: number }> {
    const { company_id, active, page = 1, limit = 20 } = filters;
    const offset = (page - 1) * limit;

    let whereClause = 'WHERE st.tenant_id = $1';
    const params: any[] = [tenantId];
    let paramIndex = 2;

    if (company_id) {
      whereClause += ` AND st.company_id = $${paramIndex++}`;
      params.push(company_id);
    }

    if (active !== undefined) {
      whereClause += ` AND st.active = $${paramIndex++}`;
      params.push(active);
    }

    const countResult = await queryOne<{ count: string }>(
      `SELECT COUNT(*) as count FROM sales.sales_teams st ${whereClause}`,
      params
    );

    params.push(limit, offset);
    const data = await query<SalesTeam>(
      `SELECT st.*,
              c.name as company_name,
              u.full_name as team_leader_name
       FROM sales.sales_teams st
       LEFT JOIN auth.companies c ON st.company_id = c.id
       LEFT JOIN auth.users u ON st.team_leader_id = u.id
       ${whereClause}
       ORDER BY st.name
       LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`,
      params
    );

    return {
      data,
      total: parseInt(countResult?.count || '0', 10),
    };
  }

  async findById(id: string, tenantId: string): Promise<SalesTeam> {
    const team = await queryOne<SalesTeam>(
      `SELECT st.*,
              c.name as company_name,
              u.full_name as team_leader_name
       FROM sales.sales_teams st
       LEFT JOIN auth.companies c ON st.company_id = c.id
       LEFT JOIN auth.users u ON st.team_leader_id = u.id
       WHERE st.id = $1 AND st.tenant_id = $2`,
      [id, tenantId]
    );

    if (!team) {
      throw new NotFoundError('Equipo de ventas no encontrado');
    }

    // Get members
    const members = await query<SalesTeamMember>(
      `SELECT stm.*,
              u.full_name as user_name,
              u.email as user_email
       FROM sales.sales_team_members stm
       LEFT JOIN auth.users u ON stm.user_id = u.id
       WHERE stm.sales_team_id = $1
       ORDER BY stm.joined_at`,
      [id]
    );

    team.members = members;

    return team;
  }

  async create(dto: CreateSalesTeamDto, tenantId: string, userId: string): Promise<SalesTeam> {
    // Check unique code in company
    if (dto.code) {
      const existing = await queryOne(
        `SELECT id FROM sales.sales_teams WHERE company_id = $1 AND code = $2`,
        [dto.company_id, dto.code]
      );
      if (existing) {
        throw new ConflictError('Ya existe un equipo con ese código en esta empresa');
      }
    }

    const team = await queryOne<SalesTeam>(
      `INSERT INTO sales.sales_teams (tenant_id, company_id, name, code, team_leader_id, target_monthly, target_annual, created_by)
       VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
       RETURNING *`,
      [tenantId, dto.company_id, dto.name, dto.code, dto.team_leader_id, dto.target_monthly, dto.target_annual, userId]
    );

    return team!;
  }

  async update(id: string, dto: UpdateSalesTeamDto, tenantId: string, userId: string): Promise<SalesTeam> {
    const team = await this.findById(id, tenantId);

    const updateFields: string[] = [];
    const values: any[] = [];
    let paramIndex = 1;

    if (dto.name !== undefined) {
      updateFields.push(`name = $${paramIndex++}`);
      values.push(dto.name);
    }
    if (dto.code !== undefined) {
      // Check unique code
      const existing = await queryOne(
        `SELECT id FROM sales.sales_teams WHERE company_id = $1 AND code = $2 AND id != $3`,
        [team.company_id, dto.code, id]
      );
      if (existing) {
        throw new ConflictError('Ya existe un equipo con ese código en esta empresa');
      }
      updateFields.push(`code = $${paramIndex++}`);
      values.push(dto.code);
    }
    if (dto.team_leader_id !== undefined) {
      updateFields.push(`team_leader_id = $${paramIndex++}`);
      values.push(dto.team_leader_id);
    }
    if (dto.target_monthly !== undefined) {
      updateFields.push(`target_monthly = $${paramIndex++}`);
      values.push(dto.target_monthly);
    }
    if (dto.target_annual !== undefined) {
      updateFields.push(`target_annual = $${paramIndex++}`);
      values.push(dto.target_annual);
    }
    if (dto.active !== undefined) {
      updateFields.push(`active = $${paramIndex++}`);
      values.push(dto.active);
    }

    updateFields.push(`updated_by = $${paramIndex++}`);
    values.push(userId);
    updateFields.push(`updated_at = CURRENT_TIMESTAMP`);

    values.push(id, tenantId);

    await query(
      `UPDATE sales.sales_teams SET ${updateFields.join(', ')}
       WHERE id = $${paramIndex++} AND tenant_id = $${paramIndex}`,
      values
    );

    return this.findById(id, tenantId);
  }

  async addMember(teamId: string, userId: string, role: string, tenantId: string): Promise<SalesTeamMember> {
    await this.findById(teamId, tenantId);

    // Check if already member
    const existing = await queryOne(
      `SELECT id FROM sales.sales_team_members WHERE sales_team_id = $1 AND user_id = $2`,
      [teamId, userId]
    );
    if (existing) {
      throw new ConflictError('El usuario ya es miembro de este equipo');
    }

    const member = await queryOne<SalesTeamMember>(
      `INSERT INTO sales.sales_team_members (sales_team_id, user_id, role)
       VALUES ($1, $2, $3)
       RETURNING *`,
      [teamId, userId, role]
    );

    return member!;
  }

  async removeMember(teamId: string, memberId: string, tenantId: string): Promise<void> {
    await this.findById(teamId, tenantId);

    await query(
      `DELETE FROM sales.sales_team_members WHERE id = $1 AND sales_team_id = $2`,
      [memberId, teamId]
    );
  }
}

export const salesTeamsService = new SalesTeamsService();
