import { ImageIcon, Loader2, Upload } from 'lucide-react';
import { useRef, useState } from 'react';
import { uploadImage } from '@/components/quote/BlockEditors';
import type { Theme } from '@/components/proposal/ThemeCard';
import { Button } from '@/components/ui/button';
import { Card, CardBody, CardHeader } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Field, FieldError } from '@/components/ui/label';

/**
 * The cover page hero image. On the A4 cover the image sits in a 417 × 380 px frame (left of the
 * "Prepared for" and "Valid until" cards); it's scaled to fill that frame and cropped from the centre.
 * We ask for 3× that for sharp print: 1250 × 1140 px.
 */
export const COVER = { w: 1250, h: 1140, minW: 840, minH: 760 } as const;

export function CoverImageCard({ theme, onChange, disabled = false }: { theme: Theme; onChange: (t: Theme) => void; disabled?: boolean }) {
    const input = useRef<HTMLInputElement>(null);
    const [busy, setBusy] = useState(false);
    const [err, setErr] = useState<string | null>(null);
    const [warn, setWarn] = useState<string | null>(null);
    const url = theme.cover_image_url ?? null;

    const pick = async (f: File) => {
        setBusy(true); setErr(null); setWarn(null);
        try {
            const d = await uploadImage(f);
            onChange({ ...theme, cover_image: d.path, cover_image_url: d.url });
            if (d.width && d.height) {
                const ratio = d.width / d.height;
                const target = COVER.w / COVER.h;
                if (d.width < COVER.minW || d.height < COVER.minH) setWarn(`This image is ${d.width} × ${d.height} px, so it may look soft when printed. Use at least ${COVER.minW} × ${COVER.minH} px.`);
                else if (Math.abs(ratio - target) / target > 0.15) setWarn(`This image is ${d.width} × ${d.height} px, a different shape to the frame, so the ${ratio > target ? 'left and right sides' : 'top and bottom'} will be cropped. Check the preview below.`);
            }
        } catch (e) {
            setErr(e instanceof Error ? e.message : 'Upload failed.');
        } finally {
            setBusy(false);
            if (input.current) input.current.value = '';
        }
    };
    const remove = () => { setWarn(null); onChange({ ...theme, cover_image: null, cover_image_url: null, cover_alt: null }); };

    return (
        <Card data-testid="cover-image-card">
            <CardHeader title="Cover image" description="The large image on the cover page, beside the Prepared for and Valid until cards." />
            <CardBody>
                <fieldset disabled={disabled} className="grid gap-5 sm:grid-cols-[minmax(0,240px)_1fr]">
                    <div>
                        <input ref={input} type="file" accept="image/jpeg,image/png,image/webp" className="sr-only" aria-label="Upload cover image"
                            data-testid="cover-image-input" onChange={(e) => { const f = e.target.files?.[0]; if (f) void pick(f); }} />
                        {/* Same shape as the frame on the cover, so what you see here is what prints. */}
                        <button type="button" onClick={() => input.current?.click()} disabled={busy || disabled}
                            className="relative flex aspect-[417/380] w-full items-center justify-center overflow-hidden rounded-[14px] border border-dashed border-line-strong bg-stone-50 text-ink-muted hover:border-accent hover:text-link"
                            title={url ? 'Replace the cover image' : 'Upload a cover image'} data-testid="cover-image-frame">
                            {url
                                ? <img src={url} alt={theme.cover_alt ?? ''} className="absolute inset-0 h-full w-full object-cover" data-testid="cover-image-preview" />
                                : <span className="flex flex-col items-center gap-1.5 text-xs">{busy ? <Loader2 className="h-5 w-5 animate-spin" /> : <ImageIcon className="h-5 w-5" />}{busy ? 'Uploading…' : 'Upload image'}</span>}
                        </button>
                        <div className="mt-2 flex gap-2">
                            <Button type="button" size="sm" variant="secondary" onClick={() => input.current?.click()} disabled={busy || disabled}>
                                {busy ? <Loader2 className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />} {url ? 'Replace' : 'Upload'}
                            </Button>
                            {url && <Button type="button" size="sm" variant="ghost" onClick={remove} data-testid="cover-image-remove">Remove</Button>}
                        </div>
                        {err && <FieldError message={err} />}
                    </div>
                    <div className="space-y-3 text-sm">
                        <div className="rounded-md bg-stone-50 px-3 py-2.5" data-testid="cover-image-help">
                            <p className="font-medium">Size for an exact fit</p>
                            <ul className="mt-1 list-disc space-y-0.5 pl-4 text-ink-muted">
                                <li><b className="text-ink">{COVER.w} × {COVER.h} px</b> (almost square, slightly wider than tall)</li>
                                <li>At least {COVER.minW} × {COVER.minH} px so it prints sharply</li>
                                <li>JPG, PNG or WebP, up to 10 MB</li>
                                <li>Other shapes are cropped from the centre to fill the frame, so keep the subject in the middle</li>
                            </ul>
                        </div>
                        {warn && <p role="status" className="rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-amber-900" data-testid="cover-image-warning">{warn}</p>}
                        {url && (
                            <Field label="Describe the image" htmlFor="cover-alt" hint="For screen readers, e.g. “New office fit-out, reception”.">
                                <Input id="cover-alt" value={theme.cover_alt ?? ''} maxLength={200} onChange={(e) => onChange({ ...theme, cover_alt: e.target.value })} />
                            </Field>
                        )}
                        {!url && <p className="text-xs text-ink-muted">No image: the cover shows the Prepared for and Valid until cards on their own. Images added under Items stay exactly where you place them.</p>}
                    </div>
                </fieldset>
            </CardBody>
        </Card>
    );
}
