import { FieldValueResponse } from '@/services/agents.service';

// Experience data structure expected by ExperienceSection component
export interface ExperienceData {
  years: string;
  yearsLabel: string;
  contracts: string;
  contractsLabel: string;
  licensingAreas: string[];
  licensingAreasLabel: string;
  expertiseYears: { area: string; years: string }[];
  expertiseYearsLabel: string;
  certifications: { name: string; org: string }[];
  certificationsLabel: string;
  agencyName: string;
  agencyDesignation: string;
  agencyShowDesignation: boolean;
  agencySectionLabel: string;
}

// Certification entry from repeater field
interface CertificationEntry {
  certification_name?: string;
  issuing_organization?: string;
  issue_date?: string;
  expiration_date?: string;
}

// Helper to get field value by slug
function getFieldValue(fieldValues: FieldValueResponse[], slug: string): unknown {
  const field = fieldValues.find(f => f.fieldSlug === slug);
  return field?.value;
}

// Helper to get field label by slug
function getFieldLabel(fieldValues: FieldValueResponse[], slug: string): string | undefined {
  const field = fieldValues.find(f => f.fieldSlug === slug);
  return field?.fieldName;
}

// Helper to get label from value for select/radio fields
function mapYearsValueToLabel(value: string | undefined): string {
  if (!value) return '-';

  const mapping: Record<string, string> = {
    '<2': 'Less than 2 years',
    '2+': '2+ years',
    '5+': '5+ years',
    '10+': '10+ years',
  };

  return mapping[value] || value;
}

// Helper to format contracts count
// Backend stores this as a RADIO field with range labels: "<3", "3-10", "10-20", "20-50", "50+"
function formatContractsCount(value: unknown): string {
  if (!value) return '-';

  const str = String(value).trim();
  if (!str) return '-';

  // Map known range labels to display strings
  const rangeMapping: Record<string, string> = {
    '<3': 'Less than 3 Contracts',
    '3-10': '3-10 Contracts',
    '10-20': '10-20 Contracts',
    '20-50': '20-50 Contracts',
    '50+': '50+ Contracts',
  };

  if (rangeMapping[str]) return rangeMapping[str];

  // Fallback: if it's a plain number, format it
  const num = parseInt(str, 10);
  if (!isNaN(num)) return `${num} Contract${num !== 1 ? 's' : ''}`;

  // Fallback: return the raw value as-is (e.g. "Less than 3")
  return str;
}

// Parse expertise areas with years (format: "Area Name - X yrs" or just "Area Name")
function parseExpertiseAreas(value: unknown): { area: string; years: string }[] {
  if (!value || !Array.isArray(value)) return [];

  return value.map((item: string) => {
    // Check if it contains a year indicator
    const yearMatch = item.match(/^(.+?)\s*[-–]\s*(\d+)\s*(yrs?|years?)$/i);
    if (yearMatch) {
      return { area: yearMatch[1].trim(), years: `${yearMatch[2]} yrs` };
    }
    // Just area name without years
    return { area: item.trim(), years: '' };
  });
}

// Parse certification entries from repeater field
function parseCertifications(value: unknown): { name: string; org: string }[] {
  if (!value) return [];

  // If it's an array of certification entries
  if (Array.isArray(value)) {
    return value
      .filter((entry: CertificationEntry) => entry?.certification_name)
      .map((entry: CertificationEntry) => ({
        name: entry.certification_name || '',
        org: entry.issuing_organization || '',
      }));
  }

  return [];
}

/**
 * Maps field values from API response to ExperienceData structure
 */
export function mapFieldValuesToExperience(fieldValues: FieldValueResponse[]): ExperienceData {
  // Get years in business (could be years_in_business from Professional or Lender experience)
  const yearsInBusiness = getFieldValue(fieldValues, 'years_in_business') as string | undefined;

  // Get contracts completed
  const contractsCompleted = getFieldValue(fieldValues, 'contracts_completed');

  // Get licensing areas (could be licensed_areas from Professional or Lender)
  const licensedAreas = getFieldValue(fieldValues, 'licensed_areas') as string[] | undefined;

  // Get expertise areas with years
  const expertiseAreas = getFieldValue(fieldValues, 'expertise_areas') as string[] | undefined;

  // Get certification entries from repeater
  const certificationEntries = getFieldValue(fieldValues, 'certification_entries');

  // Agency & Designation fields
  const agencyName = getFieldValue(fieldValues, 'agency_name') as string | undefined;
  const agencyDesignation = getFieldValue(fieldValues, 'agency_designation') as string | undefined;
  const agencyShowDesignation = getFieldValue(fieldValues, 'agency_show_designation');

  return {
    years: mapYearsValueToLabel(yearsInBusiness),
    yearsLabel: getFieldLabel(fieldValues, 'years_in_business') || 'Years in Experience',
    contracts: formatContractsCount(contractsCompleted),
    contractsLabel: getFieldLabel(fieldValues, 'contracts_completed') || 'Number of contracts closed',
    licensingAreas: licensedAreas || [],
    licensingAreasLabel: getFieldLabel(fieldValues, 'licensed_areas') || 'Licensing & Areas',
    expertiseYears: parseExpertiseAreas(expertiseAreas),
    expertiseYearsLabel: getFieldLabel(fieldValues, 'expertise_areas') || 'Areas in expertise & Years',
    certifications: parseCertifications(certificationEntries),
    certificationsLabel: getFieldLabel(fieldValues, 'certification_entries') || 'Certifications',
    agencyName: agencyName?.trim() || '',
    agencyDesignation: agencyDesignation?.trim() || '',
    agencyShowDesignation: agencyShowDesignation === true || agencyShowDesignation === 'true',
    agencySectionLabel: getFieldLabel(fieldValues, 'agency_name') || 'Real Estate Agency & Designation',
  };
}

/**
 * Check if experience data has any meaningful content
 */
export function hasExperienceData(experience: ExperienceData): boolean {
  return (
    experience.years !== '-' ||
    experience.contracts !== '-' ||
    experience.licensingAreas.length > 0 ||
    experience.expertiseYears.length > 0 ||
    experience.certifications.length > 0 ||
    experience.agencyName.length > 0
  );
}

// Profile card data structure
export interface ProfileCardData {
  bio: string;
  expertise: string[];
  serviceAreas: string[];
  city: string | null;
  state: string | null;
}

// Contact info data structure
export interface ContactInfoData {
  email: string | null;
  phone: string | null;
}

/**
 * Maps field values to contact info data (email, phone)
 */
export function mapFieldValuesToContactInfo(fieldValues: FieldValueResponse[]): ContactInfoData {
  // Get phone from various possible field slugs
  const phoneNumber = getFieldValue(fieldValues, 'phone_number') as string | undefined;
  const phone = getFieldValue(fieldValues, 'phone') as string | undefined;
  const cellNumber = getFieldValue(fieldValues, 'cell_number') as string | undefined;
  const officeNumber = getFieldValue(fieldValues, 'office_number') as string | undefined;

  // Get email from various possible field slugs
  const emailField = getFieldValue(fieldValues, 'email') as string | undefined;
  const emailAddress = getFieldValue(fieldValues, 'email_address') as string | undefined;

  return {
    email: emailField || emailAddress || null,
    phone: phoneNumber || phone || cellNumber || officeNumber || null,
  };
}

// Dynamic field data structure for SpecializationSection component
// Each field within the "Specialization" section becomes a card
export interface SpecializationFieldItem {
  fieldSlug: string;
  fieldName: string;
  icon?: string;
  values: string[];
}

export interface SpecializationFieldsData {
  fields: SpecializationFieldItem[];
}

// Availability data structure
export interface AvailabilityData {
  type: string;
  schedule: string[];
  label: string;
}

// Work environment data structure
export interface WorkEnvironmentData {
  label: string;
  content: string;
}

/**
 * Maps field values to work environment data (label + content)
 */
export function mapFieldValuesToWorkEnvironment(fieldValues: FieldValueResponse[]): WorkEnvironmentData {
  const field = fieldValues.find(f => f.fieldSlug === 'preferred_work_environment');
  return {
    label: field?.fieldName || 'Preferred Work Environment',
    content: (field?.value as string | undefined)?.trim() || '',
  };
}

// Personal tagline data structure
export interface PersonalTaglineData {
  label: string;
  content: string;
}

/**
 * Maps field values to personal tagline data (label + content)
 */
export function mapFieldValuesToPersonalTagline(fieldValues: FieldValueResponse[]): PersonalTaglineData {
  const field = fieldValues.find(f => f.fieldSlug === 'personal_tagline');
  return {
    label: field?.fieldName || 'Personal Tagline',
    content: (field?.value as string | undefined)?.trim() || '',
  };
}

// Type-determining values (business hours → Full-time, etc.)
const fullTimeKeywords = ['full_time', 'mf_9_5', 'mf_8_6', 'full time', '9-5', '9 am', '9am'];
const partTimeKeywords = ['part_time', 'part time'];
const flexibleKeywords = ['flexible'];

function matchesKeyword(value: string, keywords: string[]): boolean {
  const normalized = value.toLowerCase();
  return keywords.some(kw => normalized.includes(kw));
}

/**
 * Maps field values to availability data
 * Uses backend-resolved `valueLabel` and deduplicates by normalized label.
 */
export function mapFieldValuesToAvailability(fieldValues: FieldValueResponse[]): AvailabilityData {
  const field = fieldValues.find(f => f.fieldSlug === 'availability');
  const label = field?.fieldName || 'Availability';

  const rawValues = (field?.value as string[] | undefined) || [];
  const labelValues = (field?.valueLabel as string[] | undefined) || [];

  if (rawValues.length === 0) {
    return { type: '', schedule: [], label };
  }

  // Helper to format snake_case strings to Title Case (for unresolved raw values)
  const formatIfSnakeCase = (s: string): string => {
    const trimmed = s.trim();
    // If it looks like a snake_case key (e.g. "mf_9_5"), format it
    if (/^[a-z0-9]+(_[a-z0-9]+)+$/i.test(trimmed)) {
      return trimmed.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
    }
    return trimmed;
  };

  // Backend now strips orphan entries and returns only resolvable option labels,
  // so we trust valueLabel as-is.
  const resolvedLabels: string[] = labelValues
    .filter((l): l is string => typeof l === 'string' && l.trim().length > 0)
    .map(formatIfSnakeCase);

  // Deduplicate by normalized comparison (case/whitespace insensitive)
  const seen = new Set<string>();
  const schedule: string[] = [];
  for (const item of resolvedLabels) {
    const key = item.toLowerCase().replace(/[\s,.-]+/g, '');
    if (!seen.has(key)) {
      seen.add(key);
      schedule.push(item);
    }
  }

  // Determine availability type from resolved labels only (orphan values were already dropped).
  // If nothing valid remains, don't fabricate a type.
  let type = '';
  if (resolvedLabels.length > 0) {
    type = 'Available';
    if (resolvedLabels.some(v => matchesKeyword(v, fullTimeKeywords))) {
      type = 'Full-time';
    } else if (resolvedLabels.some(v => matchesKeyword(v, partTimeKeywords))) {
      type = 'Part-time';
    } else if (resolvedLabels.some(v => matchesKeyword(v, flexibleKeywords))) {
      type = 'Flexible';
    }
  }

  return { type, schedule, label };
}

/**
 * Helper to format snake_case values to Title Case
 */
function formatSnakeCaseToTitleCase(value: string): string {
  const trimmed = value.trim();
  // 2-letter state abbreviation: uppercase both letters
  if (/^[a-z]{2}$/i.test(trimmed)) return trimmed.toUpperCase();
  return trimmed
    .split('_')
    .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join(' ');
}

/**
 * Extract all values from a field that may be an array (multiselect) or string
 * Returns formatted values joined by comma, or null if empty
 */
function extractAllValues(value: unknown): string | null {
  if (Array.isArray(value) && value.length > 0) {
    return value.map(v => formatSnakeCaseToTitleCase(String(v))).join(', ');
  }
  if (typeof value === 'string' && value.trim()) {
    return formatSnakeCaseToTitleCase(value);
  }
  return null;
}

/**
 * Maps field values to profile card data (bio, expertise, service areas, location)
 */
export function mapFieldValuesToProfileCard(fieldValues: FieldValueResponse[]): ProfileCardData {
  // Get bio/description from various possible fields
  const description = getFieldValue(fieldValues, 'description') as string | undefined;
  const descrption = getFieldValue(fieldValues, 'descrption') as string | undefined; // typo in field slug
  const biography = getFieldValue(fieldValues, 'biography') as string | undefined;
  const bio = getFieldValue(fieldValues, 'bio') as string | undefined;

  // Get expertise from various possible fields
  const aboutMeExpertise = getFieldValue(fieldValues, 'about_me_expertise') as string[] | undefined;
  const expertiseAreas = getFieldValue(fieldValues, 'expertise_areas') as string[] | undefined;
  const specializations = getFieldValue(fieldValues, 'specializations') as string[] | undefined;
  const areasOfExpertise = getFieldValue(fieldValues, 'areas_of_expertise') as string[] | undefined;

  // Get service areas from various possible fields
  const serviceAreas = getFieldValue(fieldValues, 'service_areas') as string[] | undefined;
  const licensedAreas = getFieldValue(fieldValues, 'licensed_areas') as string[] | undefined;
  const coverageAreas = getFieldValue(fieldValues, 'coverage_areas') as string[] | undefined;

  // Get city and state from dynamic fields (multiselect fields)
  const cityValue = getFieldValue(fieldValues, 'city');
  const stateValue = getFieldValue(fieldValues, 'state');

  // City values carry a state prefix (e.g. "ne_adams") — strip before formatting
  const stripCityPrefix = (value: unknown): string | null => {
    const toPretty = (s: string) =>
      s.replace(/^[a-z]{2}_/i, '')
        .split('_')
        .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
        .join(' ');
    if (Array.isArray(value) && value.length > 0) {
      return value.map((v) => toPretty(String(v))).join(', ');
    }
    if (typeof value === 'string' && value.trim()) return toPretty(value);
    return null;
  };

  return {
    bio: description || descrption || biography || bio || '',
    expertise: aboutMeExpertise || expertiseAreas || specializations || areasOfExpertise || [],
    serviceAreas: serviceAreas || licensedAreas || coverageAreas || [],
    city: stripCityPrefix(cityValue),
    state: extractAllValues(stateValue),
  };
}

// Field slug to icon mapping for specialization fields
const fieldIconMapping: Record<string, string> = {
  'client_specialization': '/assets/icons/home-icon.svg',
  'property_type': '/assets/icons/chart-icon.svg',
  'loan_type': '/assets/icons/wallet-icon.svg',
  'areas_expertise_years': '/assets/icons/certification-icon.svg',
  'licensing_areas': '/assets/icons/location-icon.svg',
  'hobbies': '/assets/icons/heart-icon.svg',
  'hobbies_interests': '/assets/icons/heart-icon.svg',
  'price_points': '/assets/icons/wallet-icon.svg',
  'price_point': '/assets/icons/wallet-icon.svg',
  'default': '/assets/icons/home-icon.svg',
};

/**
 * Get icon for a field based on its slug
 */
function getFieldIcon(fieldSlug: string): string {
  const normalizedSlug = fieldSlug.toLowerCase();

  // Check for exact match first
  if (fieldIconMapping[normalizedSlug]) {
    return fieldIconMapping[normalizedSlug];
  }

  // Check for partial matches
  if (normalizedSlug.includes('loan')) return fieldIconMapping['loan_type'];
  if (normalizedSlug.includes('property')) return fieldIconMapping['property_type'];
  if (normalizedSlug.includes('hobby') || normalizedSlug.includes('interest')) return fieldIconMapping['hobbies'];
  if (normalizedSlug.includes('price')) return fieldIconMapping['price_points'];
  if (normalizedSlug.includes('client') || normalizedSlug.includes('special')) return fieldIconMapping['client_specialization'];
  if (normalizedSlug.includes('license') || normalizedSlug.includes('area')) return fieldIconMapping['licensing_areas'];
  if (normalizedSlug.includes('expertise') || normalizedSlug.includes('certification')) return fieldIconMapping['areas_expertise_years'];

  return fieldIconMapping['default'];
}

/**
 * Convert field value to string array for display
 */
function valueToStringArray(value: unknown): string[] {
  if (!value) return [];

  // Format snake_case values to Title Case when they look like raw keys
  // (labels from backend already have spaces, so this only affects unresolved values)
  const formatIfSnakeCase = (s: string): string => {
    const trimmed = s.trim();
    // If it contains underscores and only letters/digits, treat as snake_case
    if (/^[a-z0-9]+(_[a-z0-9]+)+$/i.test(trimmed)) {
      return formatSnakeCaseToTitleCase(trimmed);
    }
    return trimmed;
  };

  if (Array.isArray(value)) {
    // Deduplicate values
    return [...new Set(value.map(v => formatIfSnakeCase(String(v))).filter(v => v !== ''))];
  }

  if (typeof value === 'string' && value.trim()) {
    return [formatIfSnakeCase(value)];
  }

  if (typeof value === 'number' || typeof value === 'boolean') {
    return [String(value)];
  }

  return [];
}

/**
 * Maps field values from the "Specialization" section to individual field cards
 * Each field within the Specialization section becomes its own card
 */
export function mapFieldValuesToSpecializationFields(fieldValues: FieldValueResponse[]): SpecializationFieldsData {
  // Filter only fields from the "Specialization" section
  const specializationFields = fieldValues.filter(field => {
    const sectionSlug = field.sectionSlug?.toLowerCase() || '';
    return sectionSlug === 'specialization' || sectionSlug.includes('specialization');
  });

  // Create a card for each field, deduplicating by fieldSlug
  const fields: SpecializationFieldItem[] = [];
  const seenSlugs = new Set<string>();

  for (const field of specializationFields) {
    const { fieldSlug, fieldName, value, valueLabel } = field;

    // Prefer resolved labels from backend; fallback to raw value
    const displayValue = valueLabel ?? value;

    // Skip if no field info or no value
    if (!fieldSlug || !fieldName) continue;

    // Skip duplicate fieldSlugs (API may return duplicates)
    if (seenSlugs.has(fieldSlug)) continue;
    seenSlugs.add(fieldSlug);

    const values = valueToStringArray(displayValue);
    if (values.length === 0) continue;

    fields.push({
      fieldSlug,
      fieldName,
      icon: getFieldIcon(fieldSlug),
      values,
    });
  }

  return { fields };
}

/**
 * Check if specialization fields data has any meaningful content
 */
export function hasSpecializationFieldsData(data: SpecializationFieldsData): boolean {
  return data.fields.length > 0 && data.fields.some(f => f.values.length > 0);
}
