import React, { useEffect, useState } from 'react';
import { PageToolbar, SearchInput } from './shared/ui';
import axios from 'axios';
import { Button } from 'primereact/button';
import { Calendar } from 'primereact/calendar';
import { Column } from 'primereact/column';
import { ConfirmDialog, confirmDialog } from 'primereact/confirmdialog';
import { DataTable } from 'primereact/datatable';
import { Dialog } from 'primereact/dialog';
import { Dropdown } from 'primereact/dropdown';
import { Editor } from 'primereact/editor';
import { InputText } from 'primereact/inputtext';
import { InputTextarea } from 'primereact/inputtextarea';
import { Message } from 'primereact/message';
import { ProgressSpinner } from 'primereact/progressspinner';
import { TabPanel, TabView } from 'primereact/tabview';
import { Tag } from 'primereact/tag';

const STATUSES = [
    { label: 'Draft', value: 'draft' },
    { label: 'Published', value: 'published' },
];

const STATUS_SEVERITY: Record<string, 'secondary' | 'success' | 'info'> = {
    draft: 'secondary',
    published: 'success',
    scheduled: 'info',
};

const EMPTY = {
    id: null,
    slug: '',
    category_id: null as number | null,
    title_en: '',
    title_zh: '',
    excerpt_en: '',
    excerpt_zh: '',
    body_en: '',
    body_zh: '',
    status: 'draft',
    published_at: null as Date | null,
    cover: null as string | null,
    cover_file: null as File | null,
    remove_cover: false,
};

const News = () => {
    const [items, setItems] = useState([]);
    const [search, setSearch] = useState('');
    const [is_loading, setIsLoading] = useState(true);
    const [is_responding, setIsResponding] = useState(false);
    const [dialog_visible, setDialogVisible] = useState(false);
    const [error_message, setErrorMessage] = useState<string | null>(null);
    const [item, setItem] = useState<any>(EMPTY);
    const [categories, setCategories] = useState<any[]>([]);
    const [cat_visible, setCatVisible] = useState(false);
    const [cat_item, setCatItem] = useState<any>({ id: null, name_en: '', name_zh: '', slug: '', sort_order: 0 });
    const [cat_error, setCatError] = useState<string | null>(null);

    const listCategories = async () => {
        try {
            const response = await axios.get('/news_category/list');
            setCategories(response.data);
        } catch (error) {
            console.error('Failed to fetch categories:', error);
        }
    };

    const saveCategory = async () => {
        setCatError(null);
        try {
            if (cat_item.id) await axios.put('/news_category/edit', cat_item);
            else await axios.post('/news_category/add', cat_item);
            setCatItem({ id: null, name_en: '', name_zh: '', slug: '', sort_order: 0 });
            listCategories();
            list();
        } catch (error: any) {
            setCatError(firstError(error));
        }
    };

    const removeCategory = (row: any) => {
        confirmDialog({
            header: 'Delete category',
            message: `Delete "${row.name_en}"? Its ${row.news_count} post(s) become uncategorised (sent to everyone), and ${row.subscribers_count} subscriber(s) stop following it.`,
            icon: 'pi pi-exclamation-triangle',
            acceptLabel: 'Delete',
            acceptClassName: 'p-button-danger',
            accept: async () => {
                try {
                    await axios.delete('/news_category/delete', { data: { id: row.id } });
                    listCategories();
                    list();
                } catch (error: any) {
                    setCatError(firstError(error));
                }
            },
        });
    };

    const list = async () => {
        setIsLoading(true);
        try {
            const response = await axios.get('/news/list');
            setItems(response.data);
        } catch (error) {
            console.error('Failed to fetch news:', error);
        } finally {
            setIsLoading(false);
        }
    };

    useEffect(() => { list(); listCategories(); }, []);

    const add = () => {
        setErrorMessage(null);
        setItem({ ...EMPTY });
        setDialogVisible(true);
    };

    const edit = async (id: number) => {
        setErrorMessage(null);
        try {
            const response = await axios.get('/news/get?id=' + id);
            const d = response.data;
            setItem({
                ...EMPTY,
                ...d,
                title_zh: d.title_zh || '',
                excerpt_en: d.excerpt_en || '',
                excerpt_zh: d.excerpt_zh || '',
                body_zh: d.body_zh || '',
                status: d.published_at ? 'published' : 'draft',
                published_at: d.published_at ? new Date(d.published_at) : null,
            });
        } catch (error) {
            console.log(error);
        } finally {
            setDialogVisible(true);
        }
    };

    const save = async () => {
        setIsResponding(true);
        setErrorMessage(null);
        try {
            const form = new FormData();
            form.append('category_id', item.category_id ? String(item.category_id) : '');
            ['slug', 'title_en', 'title_zh', 'excerpt_en', 'excerpt_zh', 'body_en', 'body_zh'].forEach((k) =>
                form.append(k, item[k] ?? ''));
            if (item.status === 'published') {
                form.append('published_at', (item.published_at ?? new Date()).toISOString());
            } else {
                form.append('published_at', '');
            }
            if (item.cover_file) form.append('cover', item.cover_file);

            if (item.id) {
                form.append('id', String(item.id));
                form.append('remove_cover', item.remove_cover ? '1' : '0');
                // Multipart bodies only parse on POST, so the PUT route is reached via method spoofing.
                form.append('_method', 'PUT');
                await axios.post('/news/edit', form);
            } else {
                await axios.post('/news/add', form);
            }
            list();
            setDialogVisible(false);
        } catch (error: any) {
            setErrorMessage(firstError(error));
        } finally {
            setIsResponding(false);
        }
    };

    const remove = (row: any) => {
        confirmDialog({
            header: 'Delete post',
            message: `Delete "${row.title_en}"? This cannot be undone.`,
            icon: 'pi pi-exclamation-triangle',
            acceptLabel: 'Delete',
            acceptClassName: 'p-button-danger',
            accept: async () => {
                try {
                    await axios.delete('/news/delete', { data: { id: row.id } });
                    list();
                } catch (error: any) {
                    alert(firstError(error));
                }
            },
        });
    };

    const sendNewsletter = (row: any) => {
        const resend = Boolean(row.newsletter_sent_at);
        confirmDialog({
            header: resend ? 'Send again?' : 'Send to subscribers',
            message: resend
                ? `"${row.title_en}" was already emailed on ${fmtDate(row.newsletter_sent_at)}. Email every active subscriber again?`
                : `Email "${row.title_en}" to every active subscriber now?`,
            icon: 'pi pi-send',
            acceptLabel: resend ? 'Send again' : 'Send',
            acceptClassName: resend ? 'p-button-warning' : '',
            accept: async () => {
                try {
                    const response = await axios.post('/news/send', { id: row.id, resend });
                    list();
                    alert(`Queued for ${response.data.count} subscriber${response.data.count === 1 ? '' : 's'}.`);
                } catch (error: any) {
                    alert(firstError(error));
                }
            },
        });
    };

    const firstError = (error: any): string => {
        const data = error?.response?.data;
        if (data?.errors) {
            const first: any = Object.values(data.errors)[0];
            return Array.isArray(first) ? first[0] : String(first);
        }
        return data?.message || 'Something went wrong. Try again.';
    };

    const titleBodyTemplate = (row: any) => (
        <div>
            <div>{row.title_en}</div>
            {row.title_zh && <div style={{ opacity: 0.65, fontSize: '0.9em' }}>{row.title_zh}</div>}
        </div>
    );

    const statusBodyTemplate = (row: any) =>
        <Tag value={row.status[0].toUpperCase() + row.status.slice(1)} severity={STATUS_SEVERITY[row.status]} />;

    const fmtDate = (iso: string) => new Date(iso).toLocaleString('en-GB', { dateStyle: 'medium', timeStyle: 'short' });

    const dateBodyTemplate = (row: any) => (row.published_at ? fmtDate(row.published_at) : '—');

    const sentBodyTemplate = (row: any) => (row.newsletter_sent_at ? fmtDate(row.newsletter_sent_at) : '—');

    const manageBodyTemplate = (row: any) => (
        <div className="flex gap-2">
            <Button onClick={() => edit(row.id)} icon="pi pi-pencil" label="Edit" className="p-button-sm p-button-warning" />
            {row.status === 'published' && (
                <>
                    <Button onClick={() => window.open(row.url, '_blank')} icon="pi pi-external-link" label="View" className="p-button-sm p-button-secondary" />
                    <Button onClick={() => sendNewsletter(row)} icon="pi pi-send" label={row.newsletter_sent_at ? 'Resend' : 'Send'}
                        className={`p-button-sm ${row.newsletter_sent_at ? 'p-button-outlined' : 'p-button-success'}`} />
                </>
            )}
            <Button onClick={() => remove(row)} icon="pi pi-trash" label="Delete" className="p-button-sm p-button-danger" />
        </div>
    );

    const coverPreview = item.cover_file
        ? URL.createObjectURL(item.cover_file)
        : (!item.remove_cover ? item.cover : null);

    return (
        <div>
            <ConfirmDialog />
            <PageToolbar
                title="News"
                subtitle="Posts on the public /news page."
                filters={<SearchInput value={search} onChange={setSearch} placeholder="Search news…" />}
                actions={
                    <>
                        <Button icon="pi pi-refresh" onClick={list} className="p-button-text p-button-sm" />
                        <Button icon="pi pi-tags" label="Categories" onClick={() => { setCatError(null); setCatVisible(true); }} className="p-button-sm p-button-secondary" />
                        <Button icon="pi pi-plus" label="Add" onClick={add} className="p-button-sm" />
                    </>
                }
            />
            <div className="my-3">
                {is_loading ? (<ProgressSpinner style={{ width: '2rem', height: '2rem' }} className="mr-3" />) : null}
                <DataTable value={items} tableStyle={{ minWidth: '50rem' }} paginator rows={10}
                    globalFilter={search} globalFilterFields={['title_en', 'title_zh', 'slug']}
                    emptyMessage="No posts yet.">
                    <Column field="title_en" header="Title" body={titleBodyTemplate} sortable />
                    <Column field="category" header="Category" body={(r: any) => r.category || '—'} sortable />
                    <Column field="status" header="Status" body={statusBodyTemplate} sortable />
                    <Column field="published_at" header="Publish date" body={dateBodyTemplate} sortable />
                    <Column field="newsletter_sent_at" header="Emailed" body={sentBodyTemplate} sortable />
                    <Column header="Manage" body={manageBodyTemplate} />
                </DataTable>
            </div>

            <Dialog visible={cat_visible} onHide={() => setCatVisible(false)} header="News categories" modal className="p-fluid w-1/2" style={{ minWidth: '24rem' }}>
                <p style={{ opacity: 0.7, marginTop: 0 }}>Subscribers pick from these. A post goes to subscribers who follow its category or all news.</p>
                <DataTable value={categories} emptyMessage="No categories yet.">
                    <Column field="name_en" header="English" />
                    <Column field="name_zh" header="中文" body={(r: any) => r.name_zh || '—'} />
                    <Column field="news_count" header="Posts" />
                    <Column field="subscribers_count" header="Followers" />
                    <Column header="" body={(r: any) => (
                        <div className="flex gap-2">
                            <Button icon="pi pi-pencil" className="p-button-sm p-button-text" aria-label="Edit"
                                onClick={() => setCatItem({ id: r.id, name_en: r.name_en, name_zh: r.name_zh || '', slug: r.slug, sort_order: r.sort_order })} />
                            <Button icon="pi pi-trash" className="p-button-sm p-button-text p-button-danger" aria-label="Delete" onClick={() => removeCategory(r)} />
                        </div>
                    )} />
                </DataTable>
                <div className="flex gap-2 mt-3 align-items-end">
                    <div style={{ flex: 2 }}>
                        <label>{cat_item.id ? 'Edit — English' : 'New — English'}</label>
                        <InputText value={cat_item.name_en} onChange={(e) => setCatItem({ ...cat_item, name_en: e.target.value })} placeholder="e.g. Game updates" />
                    </div>
                    <div style={{ flex: 2 }}>
                        <label>中文</label>
                        <InputText value={cat_item.name_zh} onChange={(e) => setCatItem({ ...cat_item, name_zh: e.target.value })} placeholder="例如：遊戲更新" />
                    </div>
                    <div style={{ flex: 1 }}>
                        <label>Order</label>
                        <InputText keyfilter="int" value={String(cat_item.sort_order ?? 0)} onChange={(e) => setCatItem({ ...cat_item, sort_order: Number(e.target.value) || 0 })} />
                    </div>
                </div>
                <div className="flex gap-2 mt-3 align-items-center">
                    <Button label={cat_item.id ? 'Save category' : 'Add category'} onClick={saveCategory} style={{ width: 'auto' }} />
                    {cat_item.id && (
                        <Button label="Cancel" className="p-button-text" style={{ width: 'auto' }}
                            onClick={() => setCatItem({ id: null, name_en: '', name_zh: '', slug: '', sort_order: 0 })} />
                    )}
                    {cat_error ? <Message severity="error" text={cat_error} /> : null}
                </div>
            </Dialog>
            <Dialog visible={dialog_visible} onHide={() => setDialogVisible(false)}
                header={item.id ? 'Edit Post' : 'Add Post'} modal className="p-fluid w-3/4">
                <div className="form-body">
                    <div className="row">
                        <div className="col-md-12">
                            <div className="form-group mb-3">
                                <label htmlFor="category_id">Category</label>
                                <Dropdown id="category_id" value={item.category_id} options={categories} optionLabel="name_en" optionValue="id"
                                    showClear placeholder="None — sent to all subscribers"
                                    onChange={(e) => setItem({ ...item, category_id: e.value ?? null })} />
                            </div>
                        </div>
                        <div className="col-md-12">
                            <div className="form-group mb-3">
                                <label htmlFor="slug">URL slug</label>
                                <InputText id="slug" value={item.slug || ''} placeholder="Leave blank to generate from the English title"
                                    onChange={(e) => setItem({ ...item, slug: e.target.value })} />
                            </div>
                        </div>
                        <div className="col-md-12">
                            <div className="form-group mb-3 flex gap-3">
                                <div style={{ flex: 1 }}>
                                    <label htmlFor="status">Status</label>
                                    <Dropdown id="status" value={item.status} options={STATUSES}
                                        onChange={(e) => setItem({
                                            ...item,
                                            status: e.value,
                                            published_at: e.value === 'published' ? (item.published_at ?? new Date()) : null,
                                        })} />
                                </div>
                                {item.status === 'published' && (
                                    <div style={{ flex: 1 }}>
                                        <label htmlFor="published_at">Publish date (future = scheduled)</label>
                                        <Calendar id="published_at" value={item.published_at} showTime hourFormat="24"
                                            onChange={(e) => setItem({ ...item, published_at: e.value })} />
                                    </div>
                                )}
                            </div>
                        </div>
                        <div className="col-md-12">
                            <div className="form-group mb-3">
                                <label htmlFor="cover">Cover image</label>
                                {coverPreview && (
                                    <div className="flex gap-2 align-items-center mb-2">
                                        <img src={coverPreview} alt="" style={{ maxHeight: 120, borderRadius: 8 }} />
                                        <Button type="button" icon="pi pi-times" label="Remove" className="p-button-sm p-button-text p-button-danger"
                                            style={{ width: 'auto' }}
                                            onClick={() => setItem({ ...item, cover_file: null, remove_cover: true })} />
                                    </div>
                                )}
                                <input id="cover" type="file" accept="image/*"
                                    onChange={(e) => setItem({ ...item, cover_file: e.target.files?.[0] ?? null, remove_cover: false })} />
                            </div>
                        </div>
                        <div className="col-md-12">
                            <TabView>
                                <TabPanel header="English">
                                    <div className="form-group mb-3">
                                        <label htmlFor="title_en">Title</label>
                                        <InputText id="title_en" value={item.title_en} placeholder="Title"
                                            onChange={(e) => setItem({ ...item, title_en: e.target.value })} />
                                    </div>
                                    <div className="form-group mb-3">
                                        <label htmlFor="excerpt_en">Summary</label>
                                        <InputTextarea id="excerpt_en" value={item.excerpt_en} rows={2} placeholder="One or two lines shown on the news list"
                                            onChange={(e) => setItem({ ...item, excerpt_en: e.target.value })} />
                                    </div>
                                    <div className="form-group mb-3">
                                        <label>Body</label>
                                        <Editor value={item.body_en} onTextChange={(e) => setItem((i: any) => ({ ...i, body_en: e.htmlValue ?? '' }))}
                                            style={{ height: '320px' }} />
                                    </div>
                                </TabPanel>
                                <TabPanel header="中文">
                                    <p style={{ opacity: 0.65, marginBottom: 12 }}>Optional — any field left blank shows the English version.</p>
                                    <div className="form-group mb-3">
                                        <label htmlFor="title_zh">標題</label>
                                        <InputText id="title_zh" value={item.title_zh} placeholder="標題"
                                            onChange={(e) => setItem({ ...item, title_zh: e.target.value })} />
                                    </div>
                                    <div className="form-group mb-3">
                                        <label htmlFor="excerpt_zh">摘要</label>
                                        <InputTextarea id="excerpt_zh" value={item.excerpt_zh} rows={2} placeholder="摘要"
                                            onChange={(e) => setItem({ ...item, excerpt_zh: e.target.value })} />
                                    </div>
                                    <div className="form-group mb-3">
                                        <label>內容</label>
                                        <Editor value={item.body_zh} onTextChange={(e) => setItem((i: any) => ({ ...i, body_zh: e.htmlValue ?? '' }))}
                                            style={{ height: '320px' }} />
                                    </div>
                                </TabPanel>
                            </TabView>
                        </div>
                    </div>
                    <div className="flex gap-2 mt-4 align-items-center">
                        {is_responding ? (<ProgressSpinner style={{ width: '2rem', height: '2rem' }} className="mr-3" />) : null}
                        {error_message ? (<Message severity="error" text={error_message} />) : null}
                        <Button raised label="Save" onClick={save} disabled={is_responding} />
                    </div>
                </div>
            </Dialog>
        </div>
    );
};

export default News;
