/**
 * ProfileCompletionService - Seguimiento de Completitud de Perfil
 *
 * Calcula y rastrea el porcentaje de completitud del perfil de usuario.
 * Define requisitos y pesos para cada sección.
 *
 * @module Profiles
 */

import { DataSource } from 'typeorm';

interface ServiceContext {
  tenantId: string;
  userId?: string;
}

/**
 * Profile completion section
 */
export interface CompletionSection {
  id: string;
  name: string;
  description: string;
  weight: number;
  completed: boolean;
  percentage: number;
  requirements: CompletionRequirement[];
}

/**
 * Individual requirement within a section
 */
export interface CompletionRequirement {
  id: string;
  name: string;
  description: string;
  required: boolean;
  completed: boolean;
  actionUrl?: string;
}

/**
 * Overall completion status
 */
export interface ProfileCompletionStatus {
  userId: string;
  overallPercentage: number;
  sections: CompletionSection[];
  completedSections: number;
  totalSections: number;
  nextSteps: CompletionRequirement[];
  lastUpdated: Date;
}

/**
 * User data for completion check
 */
export interface UserProfileData {
  // Basic Info
  firstName?: string;
  lastName?: string;
  email?: string;
  phone?: string;
  mobilePhone?: string;

  // Avatar
  avatarUrl?: string;

  // Identity
  identificationType?: string;
  identificationNumber?: string;
  isVerified?: boolean;

  // Address
  address?: Record<string, any>;

  // Preferences
  hasPreferences?: boolean;
  language?: string;
  timezone?: string;

  // Security
  twoFactorEnabled?: boolean;
  passwordUpdatedAt?: Date;
  recoveryEmailSet?: boolean;

  // Professional
  jobTitle?: string;
  department?: string;
  skills?: string[];

  // Social
  linkedinUrl?: string;
  portfolioUrl?: string;
}

export class ProfileCompletionService {
  private dataSource: DataSource;

  constructor(dataSource: DataSource) {
    this.dataSource = dataSource;
  }

  /**
   * Calculate profile completion for a user
   */
  async calculateCompletion(ctx: ServiceContext, userId: string): Promise<ProfileCompletionStatus> {
    // Fetch user profile data
    const userData = await this.fetchUserData(ctx, userId);

    // Calculate each section
    const sections = this.calculateSections(userData);

    // Calculate overall percentage (weighted average)
    const totalWeight = sections.reduce((sum, s) => sum + s.weight, 0);
    const weightedSum = sections.reduce((sum, s) => sum + s.percentage * s.weight, 0);
    const overallPercentage = totalWeight > 0 ? Math.round(weightedSum / totalWeight) : 0;

    // Get next steps (incomplete required items)
    const nextSteps = this.getNextSteps(sections);

    const completedSections = sections.filter((s) => s.percentage === 100).length;

    return {
      userId,
      overallPercentage,
      sections,
      completedSections,
      totalSections: sections.length,
      nextSteps,
      lastUpdated: new Date(),
    };
  }

  /**
   * Get completion percentage only (lightweight)
   */
  async getCompletionPercentage(ctx: ServiceContext, userId: string): Promise<number> {
    const status = await this.calculateCompletion(ctx, userId);
    return status.overallPercentage;
  }

  /**
   * Get incomplete sections
   */
  async getIncompleteSections(ctx: ServiceContext, userId: string): Promise<CompletionSection[]> {
    const status = await this.calculateCompletion(ctx, userId);
    return status.sections.filter((s) => s.percentage < 100);
  }

  /**
   * Check if profile meets minimum completion threshold
   */
  async meetsMinimumCompletion(ctx: ServiceContext, userId: string, threshold: number = 50): Promise<boolean> {
    const percentage = await this.getCompletionPercentage(ctx, userId);
    return percentage >= threshold;
  }

  /**
   * Get missing required fields
   */
  async getMissingRequirements(ctx: ServiceContext, userId: string): Promise<CompletionRequirement[]> {
    const status = await this.calculateCompletion(ctx, userId);
    const missing: CompletionRequirement[] = [];

    for (const section of status.sections) {
      for (const req of section.requirements) {
        if (req.required && !req.completed) {
          missing.push(req);
        }
      }
    }

    return missing;
  }

  // ============ Private Methods ============

  private async fetchUserData(ctx: ServiceContext, userId: string): Promise<UserProfileData> {
    // In a real implementation, fetch from user tables
    // For now, return mock data structure
    try {
      const result = await this.dataSource.query(
        `SELECT
          u.first_name, u.last_name, u.email,
          p.phone, p.mobile_phone, p.identification_type, p.identification_number,
          p.is_verified, p.address
         FROM auth.users u
         LEFT JOIN auth.persons p ON u.id = p.user_id
         WHERE u.id = $1 AND u.tenant_id = $2`,
        [userId, ctx.tenantId]
      );

      if (result.length === 0) {
        return {};
      }

      const row = result[0];
      return {
        firstName: row.first_name,
        lastName: row.last_name,
        email: row.email,
        phone: row.phone,
        mobilePhone: row.mobile_phone,
        identificationType: row.identification_type,
        identificationNumber: row.identification_number,
        isVerified: row.is_verified,
        address: row.address,
      };
    } catch {
      // Tables might not exist, return empty
      return {};
    }
  }

  private calculateSections(data: UserProfileData): CompletionSection[] {
    return [
      this.calculateBasicInfoSection(data),
      this.calculateContactSection(data),
      this.calculateIdentitySection(data),
      this.calculatePreferencesSection(data),
      this.calculateSecuritySection(data),
      this.calculateProfessionalSection(data),
    ];
  }

  private calculateBasicInfoSection(data: UserProfileData): CompletionSection {
    const requirements: CompletionRequirement[] = [
      {
        id: 'first_name',
        name: 'First Name',
        description: 'Add your first name',
        required: true,
        completed: !!data.firstName,
        actionUrl: '/settings/profile',
      },
      {
        id: 'last_name',
        name: 'Last Name',
        description: 'Add your last name',
        required: true,
        completed: !!data.lastName,
        actionUrl: '/settings/profile',
      },
      {
        id: 'avatar',
        name: 'Profile Photo',
        description: 'Upload a profile photo',
        required: false,
        completed: !!data.avatarUrl,
        actionUrl: '/settings/profile/avatar',
      },
    ];

    return this.buildSection('basic_info', 'Basic Information', 'Your name and photo', 25, requirements);
  }

  private calculateContactSection(data: UserProfileData): CompletionSection {
    const requirements: CompletionRequirement[] = [
      {
        id: 'email',
        name: 'Email',
        description: 'Verify your email address',
        required: true,
        completed: !!data.email,
        actionUrl: '/settings/profile',
      },
      {
        id: 'phone',
        name: 'Phone Number',
        description: 'Add a phone number',
        required: false,
        completed: !!data.phone || !!data.mobilePhone,
        actionUrl: '/settings/profile',
      },
      {
        id: 'address',
        name: 'Address',
        description: 'Add your address',
        required: false,
        completed: !!(data.address && Object.keys(data.address).length > 0),
        actionUrl: '/settings/profile/address',
      },
    ];

    return this.buildSection('contact', 'Contact Information', 'How others can reach you', 20, requirements);
  }

  private calculateIdentitySection(data: UserProfileData): CompletionSection {
    const requirements: CompletionRequirement[] = [
      {
        id: 'id_type',
        name: 'ID Type',
        description: 'Select your identification type',
        required: false,
        completed: !!data.identificationType,
        actionUrl: '/settings/profile/identity',
      },
      {
        id: 'id_number',
        name: 'ID Number',
        description: 'Add your identification number',
        required: false,
        completed: !!data.identificationNumber,
        actionUrl: '/settings/profile/identity',
      },
      {
        id: 'verified',
        name: 'Identity Verified',
        description: 'Complete identity verification',
        required: false,
        completed: !!data.isVerified,
        actionUrl: '/settings/profile/verify',
      },
    ];

    return this.buildSection('identity', 'Identity Verification', 'Verify your identity', 15, requirements);
  }

  private calculatePreferencesSection(data: UserProfileData): CompletionSection {
    const requirements: CompletionRequirement[] = [
      {
        id: 'language',
        name: 'Language',
        description: 'Set your preferred language',
        required: false,
        completed: !!data.language,
        actionUrl: '/settings/preferences',
      },
      {
        id: 'timezone',
        name: 'Timezone',
        description: 'Set your timezone',
        required: false,
        completed: !!data.timezone,
        actionUrl: '/settings/preferences',
      },
      {
        id: 'preferences',
        name: 'UI Preferences',
        description: 'Customize your experience',
        required: false,
        completed: !!data.hasPreferences,
        actionUrl: '/settings/preferences',
      },
    ];

    return this.buildSection('preferences', 'Preferences', 'Personalize your experience', 10, requirements);
  }

  private calculateSecuritySection(data: UserProfileData): CompletionSection {
    const requirements: CompletionRequirement[] = [
      {
        id: 'two_factor',
        name: 'Two-Factor Authentication',
        description: 'Enable 2FA for extra security',
        required: false,
        completed: !!data.twoFactorEnabled,
        actionUrl: '/settings/security/2fa',
      },
      {
        id: 'password_age',
        name: 'Password Updated',
        description: 'Update password regularly',
        required: false,
        completed: this.isPasswordRecent(data.passwordUpdatedAt),
        actionUrl: '/settings/security/password',
      },
      {
        id: 'recovery_email',
        name: 'Recovery Email',
        description: 'Set up account recovery',
        required: false,
        completed: !!data.recoveryEmailSet,
        actionUrl: '/settings/security/recovery',
      },
    ];

    return this.buildSection('security', 'Security', 'Protect your account', 15, requirements);
  }

  private calculateProfessionalSection(data: UserProfileData): CompletionSection {
    const requirements: CompletionRequirement[] = [
      {
        id: 'job_title',
        name: 'Job Title',
        description: 'Add your job title',
        required: false,
        completed: !!data.jobTitle,
        actionUrl: '/settings/profile/professional',
      },
      {
        id: 'department',
        name: 'Department',
        description: 'Select your department',
        required: false,
        completed: !!data.department,
        actionUrl: '/settings/profile/professional',
      },
      {
        id: 'skills',
        name: 'Skills',
        description: 'Add your skills',
        required: false,
        completed: !!(data.skills && data.skills.length > 0),
        actionUrl: '/settings/profile/skills',
      },
    ];

    return this.buildSection('professional', 'Professional Info', 'Your work information', 15, requirements);
  }

  private buildSection(
    id: string,
    name: string,
    description: string,
    weight: number,
    requirements: CompletionRequirement[]
  ): CompletionSection {
    const completedCount = requirements.filter((r) => r.completed).length;
    const totalCount = requirements.length;
    const percentage = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0;

    return {
      id,
      name,
      description,
      weight,
      completed: percentage === 100,
      percentage,
      requirements,
    };
  }

  private getNextSteps(sections: CompletionSection[]): CompletionRequirement[] {
    const nextSteps: CompletionRequirement[] = [];

    // First, get required incomplete items
    for (const section of sections) {
      for (const req of section.requirements) {
        if (req.required && !req.completed) {
          nextSteps.push(req);
        }
      }
    }

    // If all required are done, suggest optional items
    if (nextSteps.length === 0) {
      for (const section of sections) {
        for (const req of section.requirements) {
          if (!req.completed && nextSteps.length < 3) {
            nextSteps.push(req);
          }
        }
      }
    }

    return nextSteps.slice(0, 5); // Limit to 5 suggestions
  }

  private isPasswordRecent(passwordUpdatedAt?: Date): boolean {
    if (!passwordUpdatedAt) return false;
    const ninetyDaysAgo = new Date();
    ninetyDaysAgo.setDate(ninetyDaysAgo.getDate() - 90);
    return passwordUpdatedAt > ninetyDaysAgo;
  }
}
