import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { useTranslation } from '@/hooks/use-translation';
import { cn } from '@/lib/utils';
import axios from 'axios';
import { FileText, MapPin, Plus, Trash2, Upload, Wifi, X } from 'lucide-react';
import { useEffect, useState } from 'react';
import type { FormEvent } from 'react';
import { toast } from 'sonner';
import type { EntryInstructions, EntryMediaItem } from '../types';

interface Logement {
    id: number;
    uid?: string;
    name?: string | null;
    internal_name?: string | null;
}

interface Props {
    logement: Logement;
    entryInstructions: EntryInstructions | null;
    media: EntryMediaItem[];
}

type WifiRow = { ssid: string; password: string; label: string };
type FieldErrors = Record<string, string>;

const ACCEPT = 'video/mp4,video/quicktime,video/webm,image/jpeg,image/png,image/webp,.pdf,.doc,.docx';

function formatSize(bytes: number | null): string {
    if (!bytes) return '';
    const mb = bytes / (1024 * 1024);
    return mb >= 1 ? `${mb.toFixed(1)} Mo` : `${Math.max(1, Math.round(bytes / 1024))} Ko`;
}

export default function EntryInstructionsSection({ logement, entryInstructions, media: initialMedia }: Props) {
    const { t } = useTranslation();
    const tr = (key: string, fallback: string) => t('properties.entry-instructions', key, fallback);

    // ---- Structured fields (axios PATCH, no Inertia reload → RU untouched) ----
    const initialWifi: WifiRow[] = (entryInstructions?.wifi ?? []).map((n) => ({
        ssid: n.ssid ?? '',
        password: n.password ?? '',
        label: n.label ?? '',
    }));

    const [fields, setFields] = useState({
        maps_url: entryInstructions?.maps_url ?? '',
        wifi: initialWifi.length ? initialWifi : [{ ssid: '', password: '', label: '' }],
        lockbox_code: entryInstructions?.lockbox_code ?? '',
        residence_code: entryInstructions?.residence_code ?? '',
        floor: entryInstructions?.floor ?? '',
        apartment_number: entryInstructions?.apartment_number ?? '',
        notes: entryInstructions?.notes ?? '',
    });
    const [errors, setErrors] = useState<FieldErrors>({});
    const [saving, setSaving] = useState(false);

    const setField = <K extends keyof typeof fields>(key: K, value: (typeof fields)[K]) => setFields((f) => ({ ...f, [key]: value }));

    const setWifi = (index: number, key: keyof WifiRow, value: string) =>
        setField(
            'wifi',
            fields.wifi.map((row, i) => (i === index ? { ...row, [key]: value } : row)),
        );

    const addWifi = () => setField('wifi', [...fields.wifi, { ssid: '', password: '', label: '' }]);
    const removeWifi = (index: number) => {
        const next = fields.wifi.filter((_, i) => i !== index);
        setField('wifi', next.length ? next : [{ ssid: '', password: '', label: '' }]);
    };

    async function saveFields(event: FormEvent) {
        event.preventDefault();
        setSaving(true);
        setErrors({});
        try {
            await axios.patch(route('logements.entry-instructions.update', logement.id), fields);
            toast.success(tr('saved', "Instructions d'entrée enregistrées."));
        } catch (e) {
            const resp = (e as { response?: { status?: number; data?: { errors?: Record<string, string[]> } } }).response;
            if (resp?.status === 422 && resp.data?.errors) {
                setErrors(Object.fromEntries(Object.entries(resp.data.errors).map(([k, v]) => [k, v[0]])));
            } else {
                toast.error('Erreur lors de l’enregistrement.');
            }
        } finally {
            setSaving(false);
        }
    }

    // ---- Media (axios upload/delete, local state) ----
    const [media, setMedia] = useState<EntryMediaItem[]>(initialMedia ?? []);
    const [pending, setPending] = useState<File[]>([]);
    const [previews, setPreviews] = useState<{ url: string; type: string; name: string }[]>([]);
    const [uploading, setUploading] = useState(false);
    const [mediaError, setMediaError] = useState<string | undefined>();

    useEffect(() => {
        const next = pending.map((file) => ({ url: URL.createObjectURL(file), type: file.type, name: file.name }));
        setPreviews(next);
        return () => next.forEach((p) => URL.revokeObjectURL(p.url));
    }, [pending]);

    const removePendingAt = (index: number) => setPending((p) => p.filter((_, i) => i !== index));

    async function uploadMedia(event: FormEvent) {
        event.preventDefault();
        if (!pending.length) return;
        setUploading(true);
        setMediaError(undefined);
        try {
            const fd = new FormData();
            pending.forEach((file) => fd.append('media[]', file));
            const res = await axios.post(route('logements.entry-instructions.media.store', logement.id), fd);
            setMedia(res.data.media ?? []);
            setPending([]);
            toast.success(tr('upload_success', 'Média(s) ajouté(s).'));
        } catch (e) {
            const resp = (e as { response?: { status?: number; data?: { errors?: Record<string, string[]> } } }).response;
            if (resp?.status === 422 && resp.data?.errors) {
                setMediaError(resp.data.errors['media.0']?.[0] ?? resp.data.errors.media?.[0] ?? 'Fichier invalide.');
            } else {
                toast.error('Erreur lors du téléversement.');
            }
        } finally {
            setUploading(false);
        }
    }

    async function deleteMedia(item: EntryMediaItem) {
        try {
            await axios.delete(route('logements.entry-instructions.media.delete', item.id));
            setMedia((m) => m.filter((x) => x.id !== item.id));
            toast.success(tr('delete_success', 'Média supprimé.'));
        } catch {
            toast.error('Erreur lors de la suppression.');
        }
    }

    return (
        <div className="flex flex-col gap-6">
            <div>
                <h2 className="text-xl font-semibold text-primary">{tr('page_title', "Instructions d'entrée")}</h2>
                <p className="mt-1 text-sm text-muted-foreground">{tr('page_subtitle', '')}</p>
            </div>

            {/* Structured fields */}
            <form onSubmit={saveFields}>
                <Card>
                    <CardHeader>
                        <CardTitle className="flex items-center gap-2">
                            <MapPin className="h-5 w-5" />
                            {tr('access_section', 'Accès & localisation')}
                        </CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-6">
                        <div>
                            <Label htmlFor="ei_maps_url">{tr('maps_url', 'Lien Google Maps')}</Label>
                            <Input
                                id="ei_maps_url"
                                type="url"
                                value={fields.maps_url}
                                onChange={(e) => setField('maps_url', e.target.value)}
                                placeholder={tr('maps_url_placeholder', 'https://maps.app.goo.gl/…')}
                                className="mt-1"
                            />
                            <InputError className="mt-1" message={errors.maps_url} />
                        </div>

                        <div className="space-y-3">
                            <div className="flex items-center gap-2">
                                <Wifi className="h-4 w-4" />
                                <Label>{tr('wifi', 'WiFi')}</Label>
                            </div>
                            {fields.wifi.map((network, index) => (
                                <div key={index} className="grid grid-cols-1 gap-2 sm:grid-cols-[1fr_1fr_140px_auto]">
                                    <Input value={network.ssid} onChange={(e) => setWifi(index, 'ssid', e.target.value)} placeholder={tr('wifi_ssid', 'Nom du réseau (SSID)')} />
                                    <Input value={network.password} onChange={(e) => setWifi(index, 'password', e.target.value)} placeholder={tr('wifi_password', 'Mot de passe')} />
                                    <Input value={network.label} onChange={(e) => setWifi(index, 'label', e.target.value)} placeholder={tr('wifi_label', 'Libellé')} />
                                    <Button type="button" variant="ghost" size="icon" onClick={() => removeWifi(index)} aria-label={tr('remove_wifi', 'Retirer')}>
                                        <Trash2 className="h-4 w-4" />
                                    </Button>
                                </div>
                            ))}
                            <Button type="button" variant="outline" size="sm" onClick={addWifi}>
                                <Plus className="mr-1 h-4 w-4" />
                                {tr('add_wifi', 'Ajouter un réseau')}
                            </Button>
                        </div>

                        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                            <div>
                                <Label htmlFor="ei_lockbox">{tr('lockbox_code', 'Code boîtier')}</Label>
                                <Input id="ei_lockbox" value={fields.lockbox_code} onChange={(e) => setField('lockbox_code', e.target.value)} className="mt-1" />
                                <InputError className="mt-1" message={errors.lockbox_code} />
                            </div>
                            <div>
                                <Label htmlFor="ei_residence">{tr('residence_code', 'Code résidence')}</Label>
                                <Input id="ei_residence" value={fields.residence_code} onChange={(e) => setField('residence_code', e.target.value)} className="mt-1" />
                                <InputError className="mt-1" message={errors.residence_code} />
                            </div>
                            <div>
                                <Label htmlFor="ei_floor">{tr('floor', 'Étage')}</Label>
                                <Input id="ei_floor" value={fields.floor} onChange={(e) => setField('floor', e.target.value)} className="mt-1" />
                                <InputError className="mt-1" message={errors.floor} />
                            </div>
                            <div>
                                <Label htmlFor="ei_apartment">{tr('apartment_number', 'Appartement')}</Label>
                                <Input id="ei_apartment" value={fields.apartment_number} onChange={(e) => setField('apartment_number', e.target.value)} className="mt-1" />
                                <InputError className="mt-1" message={errors.apartment_number} />
                            </div>
                        </div>

                        <div>
                            <Label htmlFor="ei_notes">{tr('notes', 'Notes')}</Label>
                            <Textarea id="ei_notes" value={fields.notes} onChange={(e) => setField('notes', e.target.value)} placeholder={tr('notes_placeholder', '')} rows={4} className="mt-1" />
                            <InputError className="mt-1" message={errors.notes} />
                        </div>

                        <div className="flex justify-end">
                            <Button type="submit" disabled={saving}>
                                {saving ? tr('saving', 'Enregistrement…') : tr('save', 'Enregistrer')}
                            </Button>
                        </div>
                    </CardContent>
                </Card>
            </form>

            {/* Media */}
            <Card>
                <CardHeader>
                    <CardTitle>{tr('media', 'Médias')}</CardTitle>
                    <CardDescription>{tr('media_hint', '')}</CardDescription>
                </CardHeader>
                <CardContent className="space-y-5">
                    <form onSubmit={uploadMedia} className="space-y-3" encType="multipart/form-data">
                        <Input type="file" accept={ACCEPT} multiple onChange={(e) => setPending(Array.from(e.target.files ?? []))} />
                        <InputError message={mediaError} />

                        {previews.length > 0 && (
                            <div className="space-y-3">
                                <Carousel className="relative w-full" opts={{ loop: previews.length > 1 }}>
                                    <CarouselContent>
                                        {previews.map((preview, index) => (
                                            <CarouselItem key={preview.url} className="w-full">
                                                <div className="relative flex h-56 w-full items-center justify-center overflow-hidden rounded-lg border bg-muted/30 md:h-72">
                                                    {preview.type.startsWith('image/') ? (
                                                        <img src={preview.url} alt={preview.name} className="h-full w-full object-contain" />
                                                    ) : preview.type.startsWith('video/') ? (
                                                        <video src={preview.url} className="h-full w-full object-contain" controls preload="metadata" />
                                                    ) : (
                                                        <span className="flex items-center gap-2 text-sm text-muted-foreground">
                                                            <FileText className="h-5 w-5" />
                                                            {preview.name}
                                                        </span>
                                                    )}
                                                    <button
                                                        type="button"
                                                        onClick={() => removePendingAt(index)}
                                                        className="absolute right-2 top-2 inline-flex h-8 w-8 items-center justify-center rounded-full bg-black/60 text-white transition hover:bg-black/80"
                                                        aria-label={tr('remove_wifi', 'Retirer')}
                                                    >
                                                        <X className="h-4 w-4" />
                                                    </button>
                                                </div>
                                                <div className="mt-2 truncate text-xs text-muted-foreground">{preview.name}</div>
                                            </CarouselItem>
                                        ))}
                                    </CarouselContent>
                                    {previews.length > 1 && (
                                        <>
                                            <CarouselPrevious className="left-2 top-1/2 -translate-y-1/2" />
                                            <CarouselNext className="right-2 top-1/2 -translate-y-1/2" />
                                        </>
                                    )}
                                </Carousel>
                                <div className="flex justify-end">
                                    <Button type="submit" disabled={uploading}>
                                        <Upload className="mr-1 h-4 w-4" />
                                        {uploading ? tr('uploading', 'Téléversement…') : tr('upload', 'Téléverser')}
                                    </Button>
                                </div>
                            </div>
                        )}
                    </form>

                    {media.length === 0 ? (
                        <p className="text-sm text-muted-foreground">{tr('no_media', 'Aucun média pour le moment.')}</p>
                    ) : (
                        <div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
                            {media.map((item) => (
                                <div key={item.id} className={cn('group relative overflow-hidden rounded-lg border bg-muted/20')}>
                                    <div className="flex h-40 w-full items-center justify-center overflow-hidden bg-black/5">
                                        {item.kind === 'image' ? (
                                            <img src={item.url} alt={item.original_name ?? ''} className="h-full w-full object-cover" />
                                        ) : item.kind === 'video' ? (
                                            <video src={item.url} className="h-full w-full object-cover" controls preload="metadata" />
                                        ) : (
                                            <a
                                                href={item.url}
                                                target="_blank"
                                                rel="noopener noreferrer"
                                                className="flex flex-col items-center gap-2 p-3 text-center text-xs text-muted-foreground hover:text-foreground"
                                            >
                                                <FileText className="h-8 w-8" />
                                                <span className="line-clamp-2 break-all">{item.original_name ?? item.file_name}</span>
                                            </a>
                                        )}
                                    </div>
                                    <div className="flex items-center justify-between gap-1 px-2 py-1.5">
                                        <span className="truncate text-[11px] text-muted-foreground">
                                            {item.original_name ?? item.file_name}
                                            {item.size ? ` · ${formatSize(item.size)}` : ''}
                                        </span>
                                        <button
                                            type="button"
                                            onClick={() => deleteMedia(item)}
                                            className="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-destructive hover:bg-destructive/10"
                                            aria-label={tr('delete_media', 'Supprimer')}
                                        >
                                            <Trash2 className="h-4 w-4" />
                                        </button>
                                    </div>
                                </div>
                            ))}
                        </div>
                    )}
                </CardContent>
            </Card>
        </div>
    );
}
