'use client';

import React, { useMemo, useState } from 'react';
import toast from 'react-hot-toast';
import { FiSave, FiX } from 'react-icons/fi';
import { updateReportHeader } from '@/lib/api/audit-report-builder.api';
import { HEADER_FIELD_META } from '@/lib/api/mappers/audit-report-builder.mappers';
import type { PanelProps } from './panelTypes';

export default function HeaderPanel({ model, canEdit, onDirty }: PanelProps) {
  const keys = model.options.editable_fields;
  const [values, setValues] = useState<Record<string, string>>({ ...model.fields });
  const [removed, setRemoved] = useState<Set<string>>(new Set());
  const [saved, setSaved] = useState<Record<string, string>>({ ...model.fields });
  const [overridden, setOverridden] = useState<Set<string>>(new Set(model.overridden));
  const [saving, setSaving] = useState(false);

  // Combined report: which booked standards are left off the printed report (cover, title, wording).
  const allStandards = model.report.all_standards ?? [];
  const isCombined = !!model.report.is_combined && allStandards.length > 0;
  const initialHidden = (model.extras.hidden_standards ?? []).map(Number);
  const [hiddenStd, setHiddenStd] = useState<number[]>(initialHidden);
  const [savedHidden, setSavedHidden] = useState<number[]>(initialHidden);
  const shownStd = allStandards.filter((s) => !hiddenStd.includes(s.id));
  const canHideMore = shownStd.length > 1;
  const hiddenDirty = isCombined && (hiddenStd.length !== savedHidden.length || hiddenStd.some((id) => !savedHidden.includes(id)));
  const hideStd = (id: number) => {
    if (!id || !canHideMore) return;
    setHiddenStd((p) => (p.includes(id) ? p : [...p, id]));
    onDirty('header', true);
  };
  const showStd = (id: number) => {
    setHiddenStd((p) => p.filter((x) => x !== id));
    onDirty('header', true);
  };

  const dirtyKeys = useMemo(
    () => keys.filter((k) => (values[k] ?? '') !== (saved[k] ?? '') || removed.has(k)),
    [keys, values, saved, removed],
  );

  const set = (k: string, v: string) => {
    setValues((p) => ({ ...p, [k]: v }));
    onDirty('header', true);
  };

  const resetToCrm = (k: string) => {
    setValues((p) => ({ ...p, [k]: model.crm_fields[k] ?? '' }));
    setRemoved((p) => new Set(p).add(k));
    onDirty('header', true);
  };

  const save = async () => {
    if (!dirtyKeys.length && !hiddenDirty) return toast('Nothing to save');
    setSaving(true);
    try {
      const fields: Record<string, string | null> = {};
      dirtyKeys.forEach((k) => {
        fields[k] = removed.has(k) ? null : (values[k] ?? '');
      });
      await updateReportHeader(model.report.id, {
        ...(dirtyKeys.length ? { fields } : {}),
        ...(hiddenDirty ? { extras: { hidden_standards: hiddenStd } } : {}),
      });
      if (hiddenDirty) setSavedHidden([...hiddenStd]);
      setSaved({ ...values });
      setOverridden((prev) => {
        const n = new Set(prev);
        dirtyKeys.forEach((k) => (removed.has(k) ? n.delete(k) : n.add(k)));
        return n;
      });
      setRemoved(new Set());
      onDirty('header', false);
      toast.success('Report details saved');
    } catch (e: any) {
      toast.error(e.message || 'Save failed');
    } finally {
      setSaving(false);
    }
  };

  return (
    <div>
      {isCombined && (
        <div className="rb-card">
          <style>{`
            .rb-std-row { display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin-top:8px; }
            .rb-std-chip { display:inline-flex; align-items:center; gap:6px; padding:4px 10px; border-radius:99px; font-size:12px; font-weight:600; background:#ede9fe; color:#5b21b6; border:1px solid #ddd6fe; }
            .rb-std-chip.is-off { background:#f3f4f6; color:#6b7280; border-color:#e5e7eb; text-decoration:line-through; }
            .rb-std-chip button { display:inline-flex; align-items:center; border:0; background:transparent; color:inherit; cursor:pointer; padding:0; line-height:1; }
            .rb-std-chip button:disabled { cursor:not-allowed; opacity:.4; }
            .rb-std-chip .rb-std-restore { text-decoration:none; font-size:11px; font-weight:700; color:#5b21b6; }
          `}</style>
          <div className="rb-card-head">
            <h3 className="rb-card-title">
              <span className="rb-card-bar" /> Standards shown on the report
            </h3>
            <span className="rb-hint">
              Combined report. Remove a standard here to leave it off the cover, title and wording of the printed report. The clause rows are not changed.
            </span>
          </div>
          <div className="rb-grid">
            <div className="rb-field is-wide">
              <label className="rb-label">Remove a standard from the report</label>
              <select
                className="rb-select"
                value=""
                disabled={!canEdit || !canHideMore}
                onChange={(e) => hideStd(Number(e.target.value))}
              >
                <option value="">{canHideMore ? '— choose a standard to remove —' : 'At least one standard must stay on the report'}</option>
                {shownStd.map((s) => (
                  <option key={s.id} value={s.id}>Remove {s.name}{s.title ? ' — ' + s.title : ''}</option>
                ))}
              </select>
              <div className="rb-std-row">
                {allStandards.map((s) => {
                  const off = hiddenStd.includes(s.id);
                  return (
                    <span key={s.id} className={`rb-std-chip${off ? ' is-off' : ''}`} title={off ? 'Not shown on the report' : 'Shown on the report'}>
                      {s.name}
                      {canEdit && (off ? (
                        <button type="button" className="rb-std-restore" onClick={() => showStd(s.id)}>restore</button>
                      ) : (
                        <button type="button" aria-label={`Remove ${s.name} from the report`} disabled={!canHideMore} onClick={() => hideStd(s.id)}><FiX size={12} /></button>
                      ))}
                    </span>
                  );
                })}
              </div>
            </div>
          </div>
        </div>
      )}

      <div className="rb-card">
        <div className="rb-card-head">
          <h3 className="rb-card-title">
            <span className="rb-card-bar" /> Organization &amp; Audit Details
          </h3>
          <span className="rb-hint">
            Values come from the CRM. Anything you type here overrides the CRM value for this report only.
          </span>
        </div>
        <div className="rb-grid">
          {keys.map((k) => {
            const meta = HEADER_FIELD_META[k] ?? { label: k };
            const isEdited = overridden.has(k) && !removed.has(k);
            const crm = model.crm_fields[k] ?? '';
            return (
              <div key={k} className={`rb-field${meta.wide ? ' is-wide' : ''}`}>
                <label className="rb-label">
                  {meta.label}
                  {isEdited && <span className="rb-edited">EDITED</span>}
                  {isEdited && canEdit && (
                    <button type="button" className="rb-link-reset" onClick={() => resetToCrm(k)}>
                      reset to CRM
                    </button>
                  )}
                </label>
                {meta.multiline ? (
                  <textarea
                    className="rb-textarea"
                    rows={3}
                    disabled={!canEdit}
                    value={values[k] ?? ''}
                    placeholder={crm || 'Not in CRM — type here'}
                    onChange={(e) => set(k, e.target.value)}
                  />
                ) : (
                  <input
                    className="rb-input"
                    disabled={!canEdit}
                    value={values[k] ?? ''}
                    placeholder={crm || 'Not in CRM — type here'}
                    onChange={(e) => set(k, e.target.value)}
                  />
                )}
              </div>
            );
          })}
        </div>
      </div>

      {canEdit && (
        <div className="rb-savebar">
          {(dirtyKeys.length > 0 || hiddenDirty) && <span className="rb-hint">{dirtyKeys.length + (hiddenDirty ? 1 : 0)} unsaved change(s)</span>}
          <button className="rb-btn rb-btn-primary" onClick={save} disabled={saving || (!dirtyKeys.length && !hiddenDirty)}>
            <FiSave size={14} /> {saving ? 'Saving…' : 'Save Details'}
          </button>
        </div>
      )}
    </div>
  );
}
