import React, {FormEvent, useEffect, useMemo, useState} from 'react';
import {router, usePage} from '@inertiajs/react';
import axios from 'axios';
import AppPageHeader from '@/components/AppPageHeader';
import MainLayout from '@/layouts/MainLayout';
import Modal from '@/components/ui/modal/Modal';
import {makeGetRequest, makePostRequest, makePutRequest} from '@/lib/request';
import {notify} from '@/lib/notify';
import DocumentDetailModal from './partials/DocumentDetailModal';

type Props = {id: string | number};

const classifications = ['public', 'internal', 'confidential', 'restricted'];

function label(value?: string | null): string {
    if (!value) return '—';
    return value.replaceAll('_', ' ').replace(/\b\w/g, letter => letter.toUpperCase());
}

export default function Show({id}: Props): JSX.Element {
    const {auth} = usePage<{auth: {user: any}}>().props;
    const token = auth?.user?.token ?? auth?.user?.api_token;
    const permissions: string[] = auth?.user?.user_permissions ?? [];
    const [document, setDocument] = useState<any | null>(null);
    const [matters, setMatters] = useState<any[]>([]);
    const [lawyers, setLawyers] = useState<any[]>([]);
    const [loading, setLoading] = useState(true);
    const [editOpen, setEditOpen] = useState(false);
    const [accessOpen, setAccessOpen] = useState(false);
    const [submitting, setSubmitting] = useState(false);
    const [accessUserId, setAccessUserId] = useState('');
    const [accessPermission, setAccessPermission] = useState('view');
    const [form, setForm] = useState({
        title: '', document_type: '', description: '', client_matter_id: '', litigation_case_id: '',
        responsible_lawyer_id: '', confidentiality_classification: 'internal', signature_required: false,
    });

    const selectedMatter = useMemo(() => matters.find(item => item.id === Number(form.client_matter_id)), [matters, form.client_matter_id]);

    async function loadDocument() {
        try {
            const response = await makeGetRequest(`/api/documents/${id}`, {token});
            setDocument(response.data?.result ?? response.data);
        } catch (error: any) {
            notify.toastErrorMessage(error?.response?.data?.message || 'Unable to load document');
        } finally {
            setLoading(false);
        }
    }

    async function loadReferences() {
        try {
            const response = await makeGetRequest('/api/documents/references', {token});
            const result = response.data?.result ?? {};
            setMatters(result.matters ?? []);
            setLawyers(result.lawyers ?? []);
        } catch (error: any) {
            notify.toastErrorMessage(error?.response?.data?.message || 'Unable to load document references');
        }
    }

    useEffect(() => {
        loadDocument();
        loadReferences();
    }, [id, token]);

    function openEdit() {
        if (!document) return;
        setForm({
            title: document.title ?? '',
            document_type: document.document_type ?? '',
            description: document.description ?? '',
            client_matter_id: String(document.client_matter_id ?? ''),
            litigation_case_id: String(document.litigation_case_id ?? ''),
            responsible_lawyer_id: String(document.responsible_lawyer_id ?? ''),
            confidentiality_classification: document.confidentiality_classification ?? 'internal',
            signature_required: Boolean(document.signature_required),
        });
        setEditOpen(true);
    }

    async function saveDocument(event: FormEvent) {
        event.preventDefault();
        setSubmitting(true);
        try {
            await makePutRequest(`/api/documents/${id}`, {
                ...form,
                client_matter_id: Number(form.client_matter_id),
                litigation_case_id: form.litigation_case_id ? Number(form.litigation_case_id) : null,
                responsible_lawyer_id: form.responsible_lawyer_id ? Number(form.responsible_lawyer_id) : null,
                is_confidential: ['confidential', 'restricted'].includes(form.confidentiality_classification),
            }, {token});
            notify.toastSuccessMessage('Document metadata updated');
            setEditOpen(false);
            await loadDocument();
        } catch (error: any) {
            const errors = error?.response?.data?.errors;
            notify.toastErrorMessage(errors ? Object.values(errors).flat().join(' ') : error?.response?.data?.message || 'Unable to update document');
        } finally {
            setSubmitting(false);
        }
    }

    async function removeDocument() {
        if (!document || !confirm(`Delete “${document.title}”?`)) return;
        try {
            await axios.delete(`/api/documents/${document.id}`, {headers: token ? {Authorization: `Bearer ${token}`} : {}});
            notify.toastSuccessMessage('Document deleted');
            router.visit('/documents');
        } catch (error: any) {
            const errors = error?.response?.data?.errors;
            notify.toastErrorMessage(errors ? Object.values(errors).flat().join(' ') : error?.response?.data?.message || 'Unable to delete document');
        }
    }

    async function openAccess() {
        setAccessUserId('');
        setAccessPermission('view');
        await loadDocument();
        setAccessOpen(true);
    }

    async function grantAccess(event: FormEvent) {
        event.preventDefault();
        setSubmitting(true);
        try {
            await makePostRequest(`/api/documents/${id}/access`, {user_id: Number(accessUserId), permission: accessPermission}, {token});
            notify.toastSuccessMessage('Document access granted');
            setAccessUserId('');
            await loadDocument();
        } catch (error: any) {
            notify.toastErrorMessage(error?.response?.data?.message || 'Unable to grant access');
        } finally {
            setSubmitting(false);
        }
    }

    async function revokeAccess(userId: number) {
        if (!confirm('Revoke this user’s direct document access?')) return;
        try {
            await axios.delete(`/api/documents/${id}/access`, {
                data: {user_id: userId}, headers: token ? {Authorization: `Bearer ${token}`} : {},
            });
            notify.toastSuccessMessage('Document access revoked');
            await loadDocument();
        } catch (error: any) {
            notify.toastErrorMessage(error?.response?.data?.message || 'Unable to revoke access');
        }
    }

    return <MainLayout>
        <AppPageHeader title={document?.title ?? 'Document details'} subtitle="Documents" />
        {loading ? <div className="box"><div className="box-body py-16 text-center text-gray-500"><i className="fa fa-spinner fa-spin me-2" />Loading document…</div></div> : document ? <DocumentDetailModal
            key={`${document.id}:${document.status}:${document.updated_at}:${document.current_version?.id ?? document.current_version ?? 'none'}`}
            document={document}
            token={token}
            permissions={permissions}
            variant="page"
            onClose={() => router.visit('/documents')}
            onRefresh={loadDocument}
            onEdit={openEdit}
            onManageAccess={openAccess}
            onDelete={removeDocument}
        /> : <div className="box"><div className="box-body py-16 text-center text-gray-500">The document could not be loaded.</div></div>}

        <Modal open={editOpen} onClose={() => setEditOpen(false)} title="Edit document metadata" maxWidthClassName="max-w-2xl" footer={<><button type="button" className="ti-btn ti-btn-light" onClick={() => setEditOpen(false)}>Cancel</button><button type="submit" form="document-page-edit-form" className="ti-btn ti-btn-primary" disabled={submitting}>{submitting ? 'Saving…' : 'Save changes'}</button></>}>
            <form id="document-page-edit-form" className="grid gap-4 sm:grid-cols-2" onSubmit={saveDocument}>
                <Field title="Title"><input className="ti-form-input" required value={form.title} onChange={event => setForm({...form, title: event.target.value})} /></Field>
                <Field title="Document type/category"><input className="ti-form-input" required value={form.document_type} onChange={event => setForm({...form, document_type: event.target.value})} /></Field>
                <Field title="Matter"><select className="ti-form-input" required value={form.client_matter_id} onChange={event => { const matter = matters.find(item => item.id === Number(event.target.value)); setForm({...form, client_matter_id: event.target.value, litigation_case_id: matter?.litigation_case?.id?.toString() ?? '', responsible_lawyer_id: matter?.attorney_id?.toString() ?? ''}); }}><option value="">Select matter</option>{matters.map(item => <option key={item.id} value={item.id}>{item.reference_number} — {item.client?.name}</option>)}</select></Field>
                <Field title="Litigation case"><select className="ti-form-input" value={form.litigation_case_id} onChange={event => setForm({...form, litigation_case_id: event.target.value})}><option value="">Not linked to litigation</option>{selectedMatter?.litigation_case ? <option value={selectedMatter.litigation_case.id}>{selectedMatter.litigation_case.case_number} — {selectedMatter.litigation_case.case_title}</option> : null}</select></Field>
                <Field title="Responsible lawyer"><select className="ti-form-input" value={form.responsible_lawyer_id} onChange={event => setForm({...form, responsible_lawyer_id: event.target.value})}><option value="">Not assigned</option>{lawyers.map(item => <option key={item.id} value={item.id}>{item.name}</option>)}</select></Field>
                <Field title="Confidentiality"><select className="ti-form-input" value={form.confidentiality_classification} onChange={event => setForm({...form, confidentiality_classification: event.target.value})}>{classifications.map(item => <option key={item} value={item}>{label(item)}</option>)}</select></Field>
                <div className="sm:col-span-2"><Field title="Description"><textarea className="ti-form-input" rows={3} value={form.description} onChange={event => setForm({...form, description: event.target.value})} /></Field></div>
                <label className="flex items-center gap-2 text-sm"><input type="checkbox" checked={form.signature_required} onChange={event => setForm({...form, signature_required: event.target.checked})} />This document requires signatures</label>
            </form>
        </Modal>

        <Modal open={accessOpen} onClose={() => setAccessOpen(false)} title={document ? `Access · ${document.title}` : 'Document access'} maxWidthClassName="max-w-lg" footer={<button type="button" className="ti-btn ti-btn-light" onClick={() => setAccessOpen(false)}>Close</button>}>
            <div className="space-y-5">
                <div><h5 className="mb-2 font-semibold">Users with direct access</h5>{document?.accesses?.length ? <div className="space-y-2">{document.accesses.map((access: any) => <div key={access.id} className="flex items-center justify-between rounded border p-3"><div><div className="font-medium">{access.user?.name}</div><div className="text-xs text-gray-500">{label(access.permission)}</div></div><button type="button" className="h-8 w-8 rounded-full p-0 ti-btn ti-btn-soft-danger" title="Revoke access" onClick={() => revokeAccess(access.user_id)}><i className="fa fa-user-times" /></button></div>)}</div> : <p className="text-sm text-gray-500">No direct access grants. Matter-level permissions still apply.</p>}</div>
                <form className="space-y-3 border-t pt-4" onSubmit={grantAccess}><Field title="Matter participant"><select className="ti-form-input" required value={accessUserId} onChange={event => setAccessUserId(event.target.value)}><option value="">Select user</option>{lawyers.map(item => <option key={item.id} value={item.id}>{item.name} · {item.email}</option>)}</select></Field><Field title="Permission"><select className="ti-form-input" value={accessPermission} onChange={event => setAccessPermission(event.target.value)}><option value="view">View</option><option value="edit">Edit</option></select></Field><div className="flex justify-end"><button type="submit" className="ti-btn ti-btn-primary" disabled={submitting}>Grant access</button></div></form>
            </div>
        </Modal>
    </MainLayout>;
}

function Field({title, children}: {title: string; children: React.ReactNode}): JSX.Element {
    return <label className="block"><span className="ti-form-label">{title}</span>{children}</label>;
}
