import { defaultHowItWorksContent, defaultMasteryScale, defaultSampleReportContent } from "./defaults";
import { num, str } from "./helpers";
import type {
    CompetencyRow,
    HeatmapLegendItem,
    HeatmapStudent,
    IconCard,
    MasteryRow,
    MasteryScaleLevel,
    NarrativeSection,
    ProgressHowItWorksContent,
    ProgressSampleReportContent,
    ReadTip,
    ReadinessItem,
    ReflectionItem,
    SpiderPoint,
    TimelineItem,
} from "./types";

type Content = Record<string, unknown>;

function asRecord(value: unknown): Record<string, unknown> {
    return value != null && typeof value === "object" ? (value as Record<string, unknown>) : {};
}

function parseMasteryScale(raw: unknown, fallback: MasteryScaleLevel[]): MasteryScaleLevel[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? fallback[0] ?? defaultMasteryScale[0];
        return {
            level: num(record.level, fallbackItem.level),
            label: str(record.label, fallbackItem.label),
            color: str(record.color, fallbackItem.color),
            description: str(record.description, fallbackItem.description),
        };
    });
}

function parseIconCards(raw: unknown, fallback: IconCard[]): IconCard[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? { emoji: "📌", title: "", description: "" };
        return {
            emoji: str(record.emoji, fallbackItem.emoji),
            title: str(record.title, fallbackItem.title),
            description: str(record.description ?? record.desc, fallbackItem.description),
            color: str(record.color, fallbackItem.color ?? ""),
        };
    });
}

function parseTimeline(raw: unknown, fallback: TimelineItem[]): TimelineItem[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? {
            quarter: "",
            month: "",
            label: "",
            description: "",
        };
        return {
            quarter: str(record.quarter, fallbackItem.quarter),
            month: str(record.month, fallbackItem.month),
            label: str(record.label, fallbackItem.label),
            description: str(record.description, fallbackItem.description),
        };
    });
}

function parseTips(raw: unknown, fallback: ReadTip[]): ReadTip[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? { lead: "", text: "" };
        return {
            lead: str(record.lead, fallbackItem.lead),
            text: str(record.text, fallbackItem.text),
        };
    });
}

function parseHeatmapStudents(raw: unknown, fallback: HeatmapStudent[]): HeatmapStudent[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? { name: "", scores: [] };
        const scores = Array.isArray(record.scores)
            ? record.scores.map((score) => num(score, 1))
            : fallbackItem.scores;
        return {
            name: str(record.name, fallbackItem.name),
            scores,
        };
    });
}

function parseHeatmapLegend(raw: unknown, fallback: HeatmapLegendItem[]): HeatmapLegendItem[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? { level: 1, label: "", color: "valencia" };
        return {
            level: num(record.level, fallbackItem.level),
            label: str(record.label, fallbackItem.label),
            color: str(record.color, fallbackItem.color),
        };
    });
}

export function parseHowItWorksContent(content?: Content): ProgressHowItWorksContent {
    const defaults = defaultHowItWorksContent();
    if (!content) return defaults;

    return {
        whyTitle: str(content.whyTitle, defaults.whyTitle),
        whyIntroHtml: str(content.whyIntroHtml ?? content.whyIntro, defaults.whyIntroHtml),
        whyCards: parseIconCards(content.whyCards, defaults.whyCards),
        scaleTitle: str(content.scaleTitle, defaults.scaleTitle),
        scaleSubtitle: str(content.scaleSubtitle, defaults.scaleSubtitle),
        masteryScale: parseMasteryScale(content.masteryScale, defaults.masteryScale),
        trackTitle: str(content.trackTitle, defaults.trackTitle),
        trackIntroHtml: str(content.trackIntroHtml ?? content.trackIntro, defaults.trackIntroHtml),
        trackCards: parseIconCards(content.trackCards, defaults.trackCards),
        heatmapTitle: str(content.heatmapTitle, defaults.heatmapTitle),
        heatmapDescription: str(content.heatmapDescription, defaults.heatmapDescription),
        heatmapColumns: Array.isArray(content.heatmapColumns) && content.heatmapColumns.length > 0
            ? content.heatmapColumns.map((column) => str(column))
            : defaults.heatmapColumns,
        heatmapStudents: parseHeatmapStudents(content.heatmapStudents, defaults.heatmapStudents),
        heatmapLegend: parseHeatmapLegend(content.heatmapLegend, defaults.heatmapLegend),
        continuumHtml: str(content.continuumHtml ?? content.continuumNote, defaults.continuumHtml),
        timelineTitle: str(content.timelineTitle, defaults.timelineTitle),
        timelineSubtitle: str(content.timelineSubtitle, defaults.timelineSubtitle),
        timeline: parseTimeline(content.timeline, defaults.timeline),
        readEmoji: str(content.readEmoji, defaults.readEmoji),
        readTitle: str(content.readTitle, defaults.readTitle),
        readTips: parseTips(content.readTips, defaults.readTips),
    };
}

function parseMasteryRows(raw: unknown, fallback: MasteryRow[]): MasteryRow[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? {
            subject: "",
            outcome: "",
            gradeLevel: "",
            term1: "",
            term2: "",
        };
        return {
            subject: str(record.subject, fallbackItem.subject),
            outcome: str(record.outcome, fallbackItem.outcome),
            gradeLevel: str(record.gradeLevel, fallbackItem.gradeLevel),
            term1: str(record.term1, fallbackItem.term1),
            term2: str(record.term2, fallbackItem.term2),
        };
    });
}

function parseCompetencyRows(raw: unknown, fallback: CompetencyRow[]): CompetencyRow[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? {
            name: "",
            description: "",
            term1: "",
            term2: "",
        };
        return {
            name: str(record.name, fallbackItem.name),
            description: str(record.description, fallbackItem.description),
            term1: str(record.term1, fallbackItem.term1),
            term2: str(record.term2, fallbackItem.term2),
        };
    });
}

function parseSpiderPoints(raw: unknown, fallback: SpiderPoint[]): SpiderPoint[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? { competency: "", term1: 0, term2: 0 };
        return {
            competency: str(record.competency ?? record.name, fallbackItem.competency),
            term1: num(record.term1, fallbackItem.term1),
            term2: num(record.term2, fallbackItem.term2),
        };
    });
}

function parseReadiness(raw: unknown, fallback: ReadinessItem[]): ReadinessItem[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? { subject: "", pct: "", status: "" };
        return {
            subject: str(record.subject, fallbackItem.subject),
            pct: str(record.pct, fallbackItem.pct),
            status: str(record.status, fallbackItem.status),
        };
    });
}

function parseReflection(raw: unknown, fallback: ReflectionItem[]): ReflectionItem[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? { emoji: "", label: "", text: "" };
        return {
            emoji: str(record.emoji, fallbackItem.emoji),
            label: str(record.label, fallbackItem.label),
            text: str(record.text, fallbackItem.text),
        };
    });
}

function parseNarrative(raw: unknown, fallback: NarrativeSection[]): NarrativeSection[] {
    if (!Array.isArray(raw) || raw.length === 0) return fallback;
    return raw.map((item, index) => {
        const record = asRecord(item);
        const fallbackItem = fallback[index] ?? {
            emoji: "",
            label: "",
            text: "",
            highlight: false,
        };
        return {
            emoji: str(record.emoji, fallbackItem.emoji),
            label: str(record.label, fallbackItem.label),
            text: str(record.text, fallbackItem.text),
            highlight: Boolean(record.highlight ?? fallbackItem.highlight),
        };
    });
}

export function parseSampleReportContent(content?: Content): ProgressSampleReportContent {
    const defaults = defaultSampleReportContent();
    if (!content) return defaults;

    return {
        schoolLabel: str(content.schoolLabel, defaults.schoolLabel),
        reportTitle: str(content.reportTitle, defaults.reportTitle),
        studentName: str(content.studentName, defaults.studentName),
        studentGrade: str(content.studentGrade, defaults.studentGrade),
        studentTerm: str(content.studentTerm, defaults.studentTerm),
        studentTeacher: str(content.studentTeacher, defaults.studentTeacher),
        scaleNote: str(content.scaleNote, defaults.scaleNote),
        masteryScale: parseMasteryScale(content.masteryScale, defaults.masteryScale),
        masteryProgressTitle: str(content.masteryProgressTitle, defaults.masteryProgressTitle),
        masteryProgressSubtitle: str(content.masteryProgressSubtitle, defaults.masteryProgressSubtitle),
        masteryProgress: parseMasteryRows(content.masteryProgress, defaults.masteryProgress),
        competencyTitle: str(content.competencyTitle, defaults.competencyTitle),
        competencySubtitle: str(content.competencySubtitle, defaults.competencySubtitle),
        competencyProgress: parseCompetencyRows(content.competencyProgress, defaults.competencyProgress),
        spiderTitle: str(content.spiderTitle, defaults.spiderTitle),
        spiderSubtitle: str(content.spiderSubtitle, defaults.spiderSubtitle),
        spiderPoints: parseSpiderPoints(content.spiderPoints, defaults.spiderPoints),
        readinessTitle: str(content.readinessTitle, defaults.readinessTitle),
        readinessSubtitle: str(content.readinessSubtitle, defaults.readinessSubtitle),
        readiness: parseReadiness(content.readiness, defaults.readiness),
        reflectionTitle: str(content.reflectionTitle, defaults.reflectionTitle),
        reflectionItems: parseReflection(content.reflectionItems, defaults.reflectionItems),
        narrativeTitle: str(content.narrativeTitle, defaults.narrativeTitle),
        narrativeSections: parseNarrative(content.narrativeSections, defaults.narrativeSections),
        archiveTitle: str(content.archiveTitle, defaults.archiveTitle),
        archiveItems: Array.isArray(content.archiveItems) && content.archiveItems.length > 0
            ? content.archiveItems.map((item) => str(item))
            : defaults.archiveItems,
    };
}
