import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router';
import { useTranslation } from 'react-i18next';
import { Badge, Button, Callout, Card, IconButton, ScrollArea, Spinner, TextField } from '@olly/modern-sk';
import {
  useApplyMetadataMutation,
  useEnrichTrackMutation,
  useGetTrackQuery,
  useLazyGetMetadataMatchesQuery,
} from '../../api/endpoints/library';
import type { MetadataMatch } from '../../api/types';
import { LoadingSkeleton } from '../../components/common/LoadingSkeleton';
import { ErrorState } from '../../components/common/ErrorState';
import { Placeholder } from '../../components/common/Placeholder';

interface Props {
  /** Single-track editor vs. batch editor — both A7, same scaffold. */
  batch?: boolean;
}

/** Editable fields, kept as strings while in the form — parsed on save. */
interface FormState {
  title: string;
  artistName: string;
  albumTitle: string;
  year: string;
  genre: string;
  trackNumber: string;
}

const EMPTY_FORM: FormState = {
  title: '',
  artistName: '',
  albumTitle: '',
  year: '',
  genre: '',
  trackNumber: '',
};

const labelStyle: React.CSSProperties = {
  display: 'block',
  fontSize: '0.8125rem',
  fontWeight: 500,
  marginBottom: '0.375rem',
  color: 'var(--color-text-2)',
};

function fieldStyle(): React.CSSProperties {
  return { width: '100%' };
}

/**
 * `/tracks/:trackId/metadata` — A7 metadata editor: manual edits + AcoustID
 * match picker with a current-vs-proposed diff. `/metadata/batch` is deferred.
 */
export function MetadataEditorPage({ batch = false }: Props) {
  const { t } = useTranslation();

  if (batch) {
    return <Placeholder title={t('pages.metadataBatch')} />;
  }

  return <SingleTrackEditor />;
}

function SingleTrackEditor() {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const { trackId } = useParams<{ trackId: string }>();

  const trackQuery = useGetTrackQuery(trackId ?? '', { skip: !trackId });
  const [findMatches, matchesResult] = useLazyGetMetadataMatchesQuery();
  const [applyMetadata, applyResult] = useApplyMetadataMutation();
  const [enrichTrack, enrichResult] = useEnrichTrackMutation();

  const [form, setForm] = useState<FormState>(EMPTY_FORM);
  const [initialized, setInitialized] = useState(false);
  const [selectedMatch, setSelectedMatch] = useState<MetadataMatch | null>(null);

  // Seed the form from the loaded track exactly once — afterwards it's the
  // user's edit buffer and shouldn't be clobbered by refetches.
  useEffect(() => {
    if (initialized || !trackQuery.data) return;
    const track = trackQuery.data;
    setForm({
      title: track.title,
      artistName: track.artistName,
      albumTitle: track.albumTitle,
      year: track.year != null ? String(track.year) : '',
      genre: track.genre ?? '',
      trackNumber: track.trackNumber != null ? String(track.trackNumber) : '',
    });
    setInitialized(true);
  }, [initialized, trackQuery.data]);

  if (!trackId) {
    return <ErrorState message={t('metadataEditor.error')} />;
  }

  if (trackQuery.isLoading || !initialized) {
    return (
      <div style={{ padding: '1.5rem' }}>
        <LoadingSkeleton rows={6} />
      </div>
    );
  }

  if (trackQuery.isError || !trackQuery.data) {
    return (
      <ErrorState
        message={t('metadataEditor.error')}
        onRetry={() => trackQuery.refetch()}
      />
    );
  }

  const track = trackQuery.data;

  const updateField = (key: keyof FormState) => (value: string) =>
    setForm((prev) => ({ ...prev, [key]: value }));

  const applyMatch = (match: MetadataMatch) => {
    setForm((prev) => ({
      ...prev,
      title: match.title ?? prev.title,
      artistName: match.artist ?? prev.artistName,
      albumTitle: match.album ?? prev.albumTitle,
      year: match.year != null ? String(match.year) : prev.year,
    }));
    setSelectedMatch(null);
  };

  const handleSave = async () => {
    await applyMetadata({
      trackId,
      edit: {
        title: form.title.trim() || undefined,
        artistName: form.artistName.trim() || undefined,
        albumTitle: form.albumTitle.trim() || undefined,
        year: form.year.trim() ? Number(form.year) : undefined,
        genre: form.genre.trim() || undefined,
        trackNumber: form.trackNumber.trim() ? Number(form.trackNumber) : undefined,
      },
    }).unwrap();
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <div
        style={{
          padding: '1.25rem 1.5rem',
          borderBottom: '1px solid var(--color-border)',
          display: 'flex',
          alignItems: 'center',
          gap: '1rem',
          flexShrink: 0,
        }}
      >
        <IconButton
          variant="ghost"
          size="sm"
          onClick={() => navigate(-1)}
          aria-label={t('common.back')}
        >
          ←
        </IconButton>
        <div style={{ flex: 1, minWidth: 0 }}>
          <h2 style={{ margin: 0, fontSize: '1.125rem', fontWeight: 700 }}>
            {t('pages.metadata')}
          </h2>
          <p
            style={{
              margin: '0.125rem 0 0',
              fontSize: '0.8125rem',
              color: 'var(--color-text-3)',
              overflow: 'hidden',
              textOverflow: 'ellipsis',
              whiteSpace: 'nowrap',
            }}
          >
            {track.artistName} · {track.title}
          </p>
        </div>
      </div>

      <ScrollArea style={{ flex: 1 }}>
        <div
          style={{
            padding: '1.5rem',
            display: 'flex',
            flexDirection: 'column',
            gap: '1.25rem',
            maxWidth: 640,
          }}
        >
          {applyResult.isSuccess && (
            <Callout variant="success">{t('metadataEditor.saved')}</Callout>
          )}
          {applyResult.isError && (
            <Callout variant="danger">{t('metadataEditor.saveError')}</Callout>
          )}

          <Card>
            <div
              style={{
                padding: '1.25rem',
                display: 'flex',
                flexDirection: 'column',
                gap: '1rem',
              }}
            >
              <div>
                <label style={labelStyle}>{t('metadataEditor.fields.title')}</label>
                <TextField
                  style={fieldStyle()}
                  value={form.title}
                  onChange={(e) => updateField('title')(e.target.value)}
                />
              </div>
              <div>
                <label style={labelStyle}>{t('metadataEditor.fields.artist')}</label>
                <TextField
                  style={fieldStyle()}
                  value={form.artistName}
                  onChange={(e) => updateField('artistName')(e.target.value)}
                />
              </div>
              <div>
                <label style={labelStyle}>{t('metadataEditor.fields.album')}</label>
                <TextField
                  style={fieldStyle()}
                  value={form.albumTitle}
                  onChange={(e) => updateField('albumTitle')(e.target.value)}
                />
              </div>
              <div style={{ display: 'flex', gap: '1rem' }}>
                <div style={{ flex: 1 }}>
                  <label style={labelStyle}>{t('metadataEditor.fields.year')}</label>
                  <TextField
                    style={fieldStyle()}
                    type="number"
                    value={form.year}
                    onChange={(e) => updateField('year')(e.target.value)}
                  />
                </div>
                <div style={{ flex: 1 }}>
                  <label style={labelStyle}>{t('metadataEditor.fields.trackNumber')}</label>
                  <TextField
                    style={fieldStyle()}
                    type="number"
                    value={form.trackNumber}
                    onChange={(e) => updateField('trackNumber')(e.target.value)}
                  />
                </div>
              </div>
              <div>
                <label style={labelStyle}>{t('metadataEditor.fields.genre')}</label>
                <TextField
                  style={fieldStyle()}
                  value={form.genre}
                  onChange={(e) => updateField('genre')(e.target.value)}
                />
              </div>

              <div style={{ display: 'flex', gap: '0.5rem', justifyContent: 'flex-end' }}>
                <Button
                  variant="primary"
                  onClick={() => void handleSave()}
                  disabled={applyResult.isLoading}
                >
                  {applyResult.isLoading ? <Spinner size="sm" /> : t('metadataEditor.save')}
                </Button>
              </div>
            </div>
          </Card>

          <Card>
            <div
              style={{
                padding: '1.25rem',
                display: 'flex',
                flexDirection: 'column',
                gap: '1rem',
              }}
            >
              <div
                style={{
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'space-between',
                  gap: '0.75rem',
                }}
              >
                <div>
                  <div style={{ fontWeight: 600, fontSize: '0.9375rem' }}>
                    {t('metadataEditor.autoEnrich.title')}
                  </div>
                  <div style={{ fontSize: '0.8125rem', color: 'var(--color-text-3)' }}>
                    {t('metadataEditor.autoEnrich.hint')}
                  </div>
                </div>
                <div style={{ display: 'flex', gap: '0.5rem', flexShrink: 0 }}>
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => void enrichTrack(trackId)}
                    disabled={enrichResult.isLoading}
                  >
                    {enrichResult.isLoading ? (
                      <Spinner size="sm" />
                    ) : (
                      t('metadataEditor.autoEnrich.reEnrich')
                    )}
                  </Button>
                  <Button
                    variant="primary"
                    size="sm"
                    onClick={() => void findMatches(trackId)}
                    disabled={matchesResult.isFetching}
                  >
                    {matchesResult.isFetching ? (
                      <Spinner size="sm" />
                    ) : (
                      t('metadataEditor.autoEnrich.findMatches')
                    )}
                  </Button>
                </div>
              </div>

              {enrichResult.isSuccess && (
                <Callout variant="info">{t('metadataEditor.autoEnrich.enqueued')}</Callout>
              )}

              {matchesResult.isError && (
                <Callout variant="danger">{t('metadataEditor.autoEnrich.error')}</Callout>
              )}

              {matchesResult.isSuccess && matchesResult.data && (
                matchesResult.data.length === 0 ? (
                  <Callout variant="warning">{t('metadataEditor.autoEnrich.noMatches')}</Callout>
                ) : (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
                    {matchesResult.data.map((match) => (
                      <MatchRow
                        key={match.acoustid}
                        match={match}
                        onUse={() => setSelectedMatch(match)}
                      />
                    ))}
                  </div>
                )
              )}

              {selectedMatch && (
                <DiffView
                  current={form}
                  proposed={selectedMatch}
                  onApply={() => applyMatch(selectedMatch)}
                  onCancel={() => setSelectedMatch(null)}
                />
              )}
            </div>
          </Card>
        </div>
      </ScrollArea>
    </div>
  );
}

function MatchRow({ match, onUse }: { match: MetadataMatch; onUse: () => void }) {
  const { t } = useTranslation();
  const pct = Math.round(match.score * 100);
  return (
    <div
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: '0.75rem',
        padding: '0.625rem 0.75rem',
        border: '1px solid var(--color-border)',
        borderRadius: 8,
        background: 'var(--color-surface-1)',
      }}
    >
      <Badge variant={pct >= 80 ? 'lime' : pct >= 50 ? 'outline' : 'neutral'}>
        {pct}%
      </Badge>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div
          style={{
            fontSize: '0.875rem',
            fontWeight: 500,
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }}
        >
          {match.title ?? t('metadataEditor.matches.unknownTitle')}
        </div>
        <div
          style={{
            fontSize: '0.8125rem',
            color: 'var(--color-text-3)',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }}
        >
          {[match.artist, match.album, match.year]
            .filter((v) => v !== undefined && v !== null && v !== '')
            .join(' · ')}
        </div>
      </div>
      <Button variant="ghost" size="sm" onClick={onUse}>
        {t('metadataEditor.matches.use')}
      </Button>
    </div>
  );
}

interface DiffRowDef {
  key: 'title' | 'artistName' | 'albumTitle' | 'year';
  label: string;
  current: string;
  proposed?: string;
}

function DiffView({
  current,
  proposed,
  onApply,
  onCancel,
}: {
  current: FormState;
  proposed: MetadataMatch;
  onApply: () => void;
  onCancel: () => void;
}) {
  const { t } = useTranslation();

  const rows: DiffRowDef[] = [
    {
      key: 'title',
      label: t('metadataEditor.fields.title'),
      current: current.title,
      proposed: proposed.title,
    },
    {
      key: 'artistName',
      label: t('metadataEditor.fields.artist'),
      current: current.artistName,
      proposed: proposed.artist,
    },
    {
      key: 'albumTitle',
      label: t('metadataEditor.fields.album'),
      current: current.albumTitle,
      proposed: proposed.album,
    },
    {
      key: 'year',
      label: t('metadataEditor.fields.year'),
      current: current.year,
      proposed: proposed.year != null ? String(proposed.year) : undefined,
    },
  ];

  const changed = rows.filter(
    (row) => row.proposed !== undefined && row.proposed !== row.current,
  );

  return (
    <div
      style={{
        border: '1px solid var(--color-border)',
        borderRadius: 8,
        padding: '0.875rem 1rem',
        display: 'flex',
        flexDirection: 'column',
        gap: '0.625rem',
        background: 'var(--color-surface-1)',
      }}
    >
      <div style={{ fontWeight: 600, fontSize: '0.875rem' }}>
        {t('metadataEditor.diff.title')}
      </div>
      {changed.length === 0 ? (
        <div style={{ fontSize: '0.8125rem', color: 'var(--color-text-3)' }}>
          {t('metadataEditor.diff.noChanges')}
        </div>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: '0.375rem' }}>
          {changed.map((row) => (
            <div key={row.key} style={{ fontSize: '0.8125rem' }}>
              <span style={{ color: 'var(--color-text-3)' }}>{row.label}: </span>
              <span style={{ textDecoration: 'line-through', color: 'var(--color-text-3)' }}>
                {row.current || '—'}
              </span>
              {' → '}
              <span style={{ color: 'var(--color-accent)', fontWeight: 600 }}>
                {row.proposed || '—'}
              </span>
            </div>
          ))}
        </div>
      )}
      <div style={{ display: 'flex', gap: '0.5rem', justifyContent: 'flex-end' }}>
        <Button variant="ghost" size="sm" onClick={onCancel}>
          {t('metadataEditor.diff.cancel')}
        </Button>
        <Button variant="primary" size="sm" onClick={onApply} disabled={changed.length === 0}>
          {t('metadataEditor.diff.apply')}
        </Button>
      </div>
    </div>
  );
}
