import { SimulationService } from '../services/simulation.service';

interface RecordLike {
  [key: string]: unknown;
}

export interface SimulatorEvaluationSelectionContext {
  companyName?: string;
  dateLabel?: string;
  title?: string;
}

export interface EvaluationImprovementItem {
  id: string;
  title: string;
  behavior: string;
  effect: string;
  nextStep: string;
}

export interface SimulatorEvaluationData {
  companyName: string;
  dateLabel: string;
  evaluationLabel: string;
  interviewerEvaluationBody: string;
  interviewerEvaluationLead: string;
  interviewerEvaluationTitle: string;
  interviewerScore: number;
  interviewTitle: string;
  recommendations: string[];
  selfScore: number;
  strengths: string[];
  suggestions: EvaluationImprovementItem[];
}

function asRecord(value: unknown): RecordLike | null {
  return typeof value === 'object' && value !== null ? (value as RecordLike) : null;
}

function asString(value: unknown): string {
  return typeof value === 'string' ? value : '';
}

function asNumber(value: unknown): number | null {
  if (typeof value === 'number' && Number.isFinite(value)) {
    return value;
  }
  if (typeof value === 'string') {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : null;
  }
  return null;
}

function asStringArray(value: unknown): string[] {
  if (!Array.isArray(value)) {
    return [];
  }
  return value.map((item) => asString(item).trim()).filter(Boolean);
}

function pickString(root: RecordLike | null, keys: string[]): string {
  if (!root) {
    return '';
  }
  for (const key of keys) {
    const value = asString(root[key]).trim();
    if (value) {
      return value;
    }
  }
  return '';
}

function pickNumber(root: RecordLike | null, keys: string[]): number | null {
  if (!root) {
    return null;
  }
  for (const key of keys) {
    const value = asNumber(root[key]);
    if (value !== null) {
      return value;
    }
  }
  return null;
}

function formatDateLabel(value: string): string {
  if (!value) {
    return '';
  }
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return value;
  }
  return new Intl.DateTimeFormat('da-DK', {
    day: '2-digit',
    month: 'long',
    year: 'numeric',
  }).format(date);
}

function normalizeScore(value: number | null, fallback: number): number {
  if (value === null) {
    return fallback;
  }
  return Math.max(0, Math.min(10, Math.round(value)));
}

const FALLBACK_SUGGESTIONS: EvaluationImprovementItem[] = [
  {
    id: '1',
    title: 'Mere struktur og korthed i dine svar',
    behavior: 'Du gav nogle svar, der blev lange og gentagende i stedet for fokuserede pa kernen.',
    effect: 'Det kan gore det svaerere for intervieweren hurtigt at vurdere din erfaring og beslutninger.',
    nextStep: 'Svar i 3 trin: pointe, konkret eksempel, resultat. Sigt efter 30-60 sekunder pr. svar.',
  },
  {
    id: '2',
    title: 'Flere konkrete eksempler pa performance i service',
    behavior: 'Du fortalte om ansvar, men gav fa konkrete scenarier med handling og resultat.',
    effect: 'Uden konkrete cases bliver niveau og paalidelighed svaerere at validere.',
    nextStep: 'Forbered 2-3 STAR-historier med tydelig situation, handling og maelbart resultat.',
  },
  {
    id: '3',
    title: 'Gor din motivation mere maelrettet virksomheden',
    behavior: 'Motivationen var positiv, men ikke altid koblet direkte til virksomhedens drift og behov.',
    effect: 'Du kan fremsta generelt motiveret i stedet for specifikt relevant for rollen.',
    nextStep: 'Naevn 2-3 konkrete grunde til, at netop deres setup matcher din erfaring.',
  },
  {
    id: '4',
    title: 'Konkretiser kvalitet og sikkerhed i praksis',
    behavior: 'Du naevnte standarder og certificeringer, men beskrev fa daglige rutiner.',
    effect: 'Det reducerer tydeligheden omkring, hvordan du arbejder sikkert i travle perioder.',
    nextStep: 'Beskriv faste rutiner for kontrol, logning og hurtig korrektion under pres.',
  },
];

const FALLBACK_STRENGTHS = [
  'Du viser relevant erfaring for rollen og kommunikerer ro under pres.',
  'Du arbejder struktureret med kvalitet og timing i service.',
  'Du har en moden team-tilgang med fokus pa samarbejde.',
  'Du kobler dine svar til konkrete arbejdsrutiner og drift.',
  'Du fremstar stabil og ansvarlig i hektiske situationer.',
];

const FALLBACK_RECOMMENDATIONS = [
  'Forbered 3 korte STAR-historier med maelbare resultater.',
  'Lav en 60-sekunders pitch af din profil og vaerdiskabelse.',
  'Research virksomheden i 10-15 minutter inden samtalen.',
  'Forbered 4-5 konkrete spoergsmaal om rolle og forventninger.',
  'Afslut svar med resultat, sa din effekt bliver tydelig.',
];

const FALLBACK_DATA: SimulatorEvaluationData = {
  companyName: 'Ukendt virksomhed',
  dateLabel: 'Nyligt',
  evaluationLabel: 'Interview Feedback',
  interviewerEvaluationTitle: 'Interviewer evaluering',
  interviewerEvaluationLead: 'Du er godt med. Din praestation viste styrker der matcher stillingen.',
  interviewerEvaluationBody:
    'Du viste relevante kompetencer og en stabil tilgang under pres. Du kan staerke dit indtryk yderligere ved at svare mere struktureret og bruge flere konkrete resultateksempler.',
  interviewTitle: 'Stilling',
  interviewerScore: 8,
  selfScore: 5,
  strengths: FALLBACK_STRENGTHS,
  recommendations: FALLBACK_RECOMMENDATIONS,
  suggestions: FALLBACK_SUGGESTIONS,
};

function mapSuggestion(item: unknown, index: number): EvaluationImprovementItem | null {
  const source = asRecord(item);
  if (!source) {
    return null;
  }

  const title = pickString(source, ['title', 'heading', 'name', 'subject']);
  const behavior = pickString(source, ['behavior', 'adfaerd', 'observation', 'issue']);
  const effect = pickString(source, ['effect', 'impact', 'consequence']);
  const nextStep = pickString(source, ['next_step', 'nextStep', 'recommendation', 'suggestion']);

  if (!title && !behavior && !effect && !nextStep) {
    return null;
  }

  return {
    id: asString(source.id) || String(index + 1),
    title: title || `Forbedringspunkt ${index + 1}`,
    behavior: behavior || 'Ingen detaljer tilgaengelige.',
    effect: effect || 'Ingen detaljer tilgaengelige.',
    nextStep: nextStep || 'Ingen detaljer tilgaengelige.',
  };
}

function extractSuggestions(root: RecordLike | null): EvaluationImprovementItem[] {
  const candidates = [
    root?.suggestions,
    root?.improvements,
    root?.improvement_points,
    root?.feedback_points,
    asRecord(root?.evaluation)?.suggestions,
    asRecord(root?.evaluation)?.improvements,
  ];

  for (const candidate of candidates) {
    if (!Array.isArray(candidate)) {
      continue;
    }

    const mapped = candidate
      .map((item, index) => mapSuggestion(item, index))
      .filter((item): item is EvaluationImprovementItem => Boolean(item));

    if (mapped.length > 0) {
      return mapped;
    }
  }

  return FALLBACK_SUGGESTIONS;
}

function extractStringList(root: RecordLike | null, keys: string[], fallback: string[]): string[] {
  for (const key of keys) {
    const values = asStringArray(root?.[key]);
    if (values.length > 0) {
      return values;
    }
  }

  const evaluation = asRecord(root?.evaluation);
  for (const key of keys) {
    const values = asStringArray(evaluation?.[key]);
    if (values.length > 0) {
      return values;
    }
  }

  return fallback;
}

export class SimulatorEvaluationViewModel {
  constructor(private readonly simulationService: SimulationService = new SimulationService()) {}

  async getEvaluation(interviewId: string, context?: SimulatorEvaluationSelectionContext): Promise<SimulatorEvaluationData> {
    try {
      const payload = await this.simulationService.getInterviewEvaluation(interviewId);
      const root = asRecord(payload);
      const evaluation = asRecord(root?.evaluation);

      const companyName = pickString(root, ['company_name', 'companyName'])
        || pickString(evaluation, ['company_name', 'companyName'])
        || context?.companyName
        || FALLBACK_DATA.companyName;

      const interviewTitle = pickString(root, ['job_title', 'job_name', 'title'])
        || pickString(evaluation, ['job_title', 'job_name', 'title'])
        || context?.title
        || FALLBACK_DATA.interviewTitle;

      const rawDate = pickString(root, ['interview_date', 'created_at', 'date'])
        || pickString(evaluation, ['interview_date', 'created_at', 'date']);

      const dateLabel = formatDateLabel(rawDate) || context?.dateLabel || FALLBACK_DATA.dateLabel;

      const interviewerEvaluationLead = pickString(root, ['interviewer_evaluation_lead', 'lead'])
        || pickString(evaluation, ['interviewer_evaluation_lead', 'lead'])
        || FALLBACK_DATA.interviewerEvaluationLead;

      const interviewerEvaluationBody = pickString(root, ['interviewer_evaluation', 'summary', 'feedback'])
        || pickString(evaluation, ['interviewer_evaluation', 'summary', 'feedback'])
        || FALLBACK_DATA.interviewerEvaluationBody;

      const interviewerEvaluationTitle = pickString(root, ['evaluation_title', 'interviewer_title'])
        || pickString(evaluation, ['evaluation_title', 'interviewer_title'])
        || FALLBACK_DATA.interviewerEvaluationTitle;

      const evaluationLabel = pickString(root, ['label', 'evaluation_label'])
        || pickString(evaluation, ['label', 'evaluation_label'])
        || FALLBACK_DATA.evaluationLabel;

      const selfScore = normalizeScore(
        pickNumber(root, ['candidate_score', 'self_score', 'self_rating'])
          ?? pickNumber(evaluation, ['candidate_score', 'self_score', 'self_rating']),
        FALLBACK_DATA.selfScore,
      );

      const interviewerScore = normalizeScore(
        pickNumber(root, ['interviewer_score', 'score', 'interviewer_rating'])
          ?? pickNumber(evaluation, ['interviewer_score', 'score', 'interviewer_rating']),
        FALLBACK_DATA.interviewerScore,
      );

      return {
        companyName,
        dateLabel,
        evaluationLabel,
        interviewerEvaluationBody,
        interviewerEvaluationLead,
        interviewerEvaluationTitle,
        interviewerScore,
        interviewTitle,
        recommendations: extractStringList(root, ['recommendations', 'constructive_recommendations', 'next_steps'], FALLBACK_RECOMMENDATIONS),
        selfScore,
        strengths: extractStringList(root, ['strengths', 'highlights'], FALLBACK_STRENGTHS),
        suggestions: extractSuggestions(root),
      };
    } catch {
      return {
        ...FALLBACK_DATA,
        companyName: context?.companyName || FALLBACK_DATA.companyName,
        interviewTitle: context?.title || FALLBACK_DATA.interviewTitle,
        dateLabel: context?.dateLabel || FALLBACK_DATA.dateLabel,
      };
    }
  }

  async submitRating(interviewId: string, rating: number, comment: string): Promise<void> {
    await this.simulationService.submitEvaluationRating(interviewId, rating, comment);
  }
}
