import { type FormEvent, useCallback, useEffect, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import {
  fetchFamilyLegacyImportMeta,
  submitFamilyLegacyImport,
} from '../../api/session'
import type {
  FamilyLegacyImportMetaResponse,
  FamilyLegacyImportResult,
  FamilyLegacyImportRowError,
} from '../../api/types'

const DEFAULT_INSTRUCTIONS =
  'Upload a CSV or Excel export from the legacy system. The API validates rows and creates or updates family records. Use dry run first when available to preview without writing.'

export function FamilyLegacyImportPage() {
  const [meta, setMeta] = useState<FamilyLegacyImportMetaResponse | null>(null)
  const [metaError, setMetaError] = useState<string | null>(null)
  const [file, setFile] = useState<File | null>(null)
  const [dryRun, setDryRun] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [result, setResult] = useState<FamilyLegacyImportResult | null>(null)

  const loadMeta = useCallback(async () => {
    setMetaError(null)
    try {
      const raw = await fetchFamilyLegacyImportMeta()
      setMeta(raw)
    } catch {
      setMeta(null)
      setMetaError(
        'Could not load import instructions from the server (GET may be unconfigured). You can still upload using defaults.',
      )
    }
  }, [])

  useEffect(() => {
    void loadMeta()
  }, [loadMeta])

  const acceptAttr = useMemo(() => {
    const exts = meta?.accepted_extensions?.filter(Boolean)
    if (exts?.length) return exts.map((e) => (e.startsWith('.') ? e : `.${e}`)).join(',')
    return '.csv,.xlsx,.xls'
  }, [meta])

  const maxBytes = meta?.max_file_bytes ?? undefined

  async function onSubmit(e: FormEvent) {
    e.preventDefault()
    setError(null)
    setResult(null)
    if (!file) {
      setError('Choose a file to import.')
      return
    }
    if (maxBytes != null && file.size > maxBytes) {
      setError(`File exceeds maximum size (${maxBytes} bytes).`)
      return
    }
    setSubmitting(true)
    try {
      const fd = new FormData()
      fd.set('file', file)
      if (dryRun && meta?.dry_run_supported !== false) {
        fd.set('dry_run', '1')
      }
      const res = await submitFamilyLegacyImport(fd)
      setResult(res)
      if (res.ok === false && !res.message) {
        setError('Import completed with errors. Review the table below.')
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Import failed.')
    } finally {
      setSubmitting(false)
    }
  }

  const templateHref = meta?.template_url ?? meta?.template_download_url ?? ''
  const instructionsText = meta?.instructions?.trim() || DEFAULT_INSTRUCTIONS
  const rowErrors: FamilyLegacyImportRowError[] =
    result?.errors ?? result?.validation_errors ?? []

  const imported = result?.imported ?? result?.imported_count
  const skipped = result?.skipped ?? result?.skipped_count
  const resultOk = result?.ok !== false && rowErrors.length === 0

  return (
    <div className="container-fluid py-4" style={{ maxWidth: 720 }}>
      <nav aria-label="breadcrumb">
        <ol className="breadcrumb">
          <li className="breadcrumb-item">
            <Link to="/app/administrator/family">Families</Link>
          </li>
          <li className="breadcrumb-item active" aria-current="page">
            Import legacy
          </li>
        </ol>
      </nav>

      <h1 className="h3 mb-2">Import legacy families</h1>
      <p className="text-muted small mb-4">
        Uses <code>GET</code> / <code>POST</code> <code>/api/v1/families/import-legacy</code> with JWT{' '}
        <code>Authorization: Bearer</code>. Field name for upload: <code>file</code>.
      </p>

      {metaError ? <div className="alert alert-warning">{metaError}</div> : null}

      <div className="card shadow-sm mb-4">
        <div className="card-header">
          <strong>Instructions</strong>
        </div>
        <div className="card-body">
          {meta?.instructions_html ? (
            <div
              className="small"
              // eslint-disable-next-line react/no-danger -- API-provided HTML when present
              dangerouslySetInnerHTML={{ __html: meta.instructions_html }}
            />
          ) : (
            <p className="small mb-0" style={{ whiteSpace: 'pre-wrap' }}>
              {instructionsText}
            </p>
          )}
          {meta?.columns?.length ? (
            <div className="mt-3">
              <div className="fw-semibold small">Expected columns</div>
              <code className="small">{meta.columns.join(', ')}</code>
            </div>
          ) : null}
          {templateHref ? (
            <a className="btn btn-sm btn-outline-secondary mt-3" href={templateHref} target="_blank" rel="noreferrer">
              Download template
            </a>
          ) : null}
        </div>
      </div>

      <div className="card shadow-sm">
        <div className="card-header">
          <strong>Upload</strong>
        </div>
        <div className="card-body">
          <form onSubmit={(e) => void onSubmit(e)}>
            <div className="mb-3">
              <label className="form-label" htmlFor="legacy-import-file">
                File
              </label>
              <input
                id="legacy-import-file"
                type="file"
                className="form-control"
                accept={acceptAttr}
                required
                disabled={submitting}
                onChange={(ev) => setFile(ev.target.files?.[0] ?? null)}
              />
              {maxBytes != null ? (
                <div className="form-text">Maximum size: {maxBytes.toLocaleString()} bytes.</div>
              ) : null}
            </div>

            {(meta?.dry_run_supported ?? true) ? (
              <div className="form-check mb-3">
                <input
                  id="legacy-dry-run"
                  type="checkbox"
                  className="form-check-input"
                  checked={dryRun}
                  disabled={submitting}
                  onChange={(e) => setDryRun(e.target.checked)}
                />
                <label className="form-check-label" htmlFor="legacy-dry-run">
                  Dry run (validate only; sends <code>dry_run=1</code>)
                </label>
              </div>
            ) : null}

            {error ? <div className="alert alert-danger py-2">{error}</div> : null}

            <button type="submit" className="btn btn-primary" disabled={submitting}>
              {submitting ? 'Uploading…' : 'Run import'}
            </button>
          </form>

          {result ? (
            <div className="mt-4 pt-3 border-top">
              <div
                className={`alert mb-3 ${resultOk ? 'alert-success' : 'alert-warning'}`}
                role="status"
              >
                {result.message ?? 'Import finished.'}
              </div>
              <div className="row g-2 small mb-3">
                {imported != null ? (
                  <div className="col-auto">
                    <span className="text-muted">Imported:</span>{' '}
                    <strong>{imported}</strong>
                  </div>
                ) : null}
                {skipped != null ? (
                  <div className="col-auto">
                    <span className="text-muted">Skipped:</span>{' '}
                    <strong>{skipped}</strong>
                  </div>
                ) : null}
                {result.failed != null ? (
                  <div className="col-auto">
                    <span className="text-muted">Failed:</span>{' '}
                    <strong>{result.failed}</strong>
                  </div>
                ) : null}
              </div>
              {rowErrors.length > 0 ? (
                <div className="table-responsive">
                  <table className="table table-sm table-bordered mb-0">
                    <thead className="table-light">
                      <tr>
                        <th>Row</th>
                        <th>Error</th>
                      </tr>
                    </thead>
                    <tbody>
                      {rowErrors.map((row, i) => (
                        <tr key={`${row.row ?? row.line ?? i}-${i}`}>
                          <td>{row.row ?? row.line ?? '—'}</td>
                          <td>{row.message ?? row.error ?? '—'}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              ) : null}
            </div>
          ) : null}
        </div>
      </div>
    </div>
  )
}
