import { createRoot } from 'react-dom/client';
import { useEffect, useMemo, useState } from 'react';
import {
    App as AntdApp,
    Alert,
    Button,
    Card,
    Collapse,
    ConfigProvider,
    Form,
    Input,
    Row,
    Col,
    Space,
    Tag,
    Typography,
    theme,
} from 'antd';
import zhCN from 'antd/locale/zh_CN';
import {
    CloudUploadOutlined,
    DownloadOutlined,
    ScanOutlined,
    SettingOutlined,
} from '@ant-design/icons';
import type { ScanResult, ImageMaterial } from '../../src/collector/scan';
import { cleanFilename } from '../../src/collector/url';
import { buildProduct, type TextEdits } from '../../src/export/builder';
import { chooseRootDir, writeProductFolder, type ExportResult } from '../../src/export/filesystem';
import { loadRootDir } from '../../src/export/idb';
import { buildMaterialsPayload } from '../../src/api/client';
import { loadSettings, saveSettings, type BackendSettings } from '../../src/storage/settings';

const { Title, Text } = Typography;

const GROUP_ORDER: Array<{ key: ImageMaterial['groupKey']; name: string }> = [
    { key: 'main', name: '主图' },
    { key: 'sku', name: 'SKU图' },
    { key: 'detail', name: '详情图' },
    { key: 'video', name: '视频' },
];

function defaultSelection(result: ScanResult): Set<string> {
    const sel = new Set<string>();
    let detailCount = 0;
    for (const img of result.images) {
        if (img.groupKey === 'detail') {
            if (detailCount < 3) sel.add(img.key);
            detailCount++;
        } else {
            sel.add(img.key);
        }
    }
    return sel;
}

function norm(s: string): string {
    return s.toLowerCase().trim().replace(/[,，:：()（）]/g, '');
}

/** 从参数表里抽出「包装重量 + 包装尺寸(长宽高)」，其余参数保留 */
function extractWeightAndDims(pairs: Array<{ key: string; value: string }>): {
    weight: string;
    dims: { l: string; w: string; h: string };
    dimsUnit: 'mm' | 'cm';
    remaining: Array<{ key: string; value: string }>;
} {
    // 包装重量：优先「包装重量」，其次「重量 / вес」
    const weightP =
        pairs.find((p) => {
            const k = norm(p.key);
            return k.includes('包装重量') || k.includes('вес упаковки');
        }) ??
        pairs.find((p) => {
            const k = norm(p.key);
            return k.includes('重量') || k.includes('вес');
        });

    // 分开的长/宽/高（用「长度/宽度/高度」而非「长/宽/高」，避免误匹配「长X宽x高」这种合并键）
    const lenP = pairs.find((p) => {
        const k = norm(p.key);
        return k.includes('包装长度') || k.includes('长度') || k.includes('длина');
    });
    const widP = pairs.find((p) => {
        const k = norm(p.key);
        return k.includes('包装宽度') || k.includes('宽度') || k.includes('ширина');
    });
    const heiP = pairs.find((p) => {
        const k = norm(p.key);
        return k.includes('包装高度') || k.includes('高度') || k.includes('высота');
    });

    let l = lenP?.value ?? '';
    let w = widP?.value ?? '';
    let h = heiP?.value ?? '';
    let dimsUnit: 'mm' | 'cm' = 'cm';

    // 合并的「包装尺寸（长X宽x高），厘米 = 48*18*25」→ 拆分
    let dimP: { key: string; value: string } | undefined;
    if (!l && !w && !h) {
        dimP = pairs.find((p) => norm(p.key).includes('包装尺寸'));
        if (!dimP) dimP = pairs.find((p) => norm(p.key).includes('размер') || norm(p.key).includes('габарит'));
        if (!dimP) dimP = pairs.find((p) => norm(p.key).includes('尺寸'));
        if (dimP) {
            const isMm = /(мм|mm|毫米)/.test(`${dimP.key} ${dimP.value}`.toLowerCase());
            dimsUnit = isMm ? 'mm' : 'cm';
            const nums = dimP.value.match(/\d+(?:[.,]\d+)?/g) ?? [];
            if (nums.length >= 3) {
                l = nums[0] ?? '';
                w = nums[1] ?? '';
                h = nums[2] ?? '';
            }
        }
    } else {
        const combined = `${lenP?.key ?? ''} ${lenP?.value ?? ''} ${widP?.value ?? ''} ${heiP?.value ?? ''}`.toLowerCase();
        dimsUnit = /(мм|mm|毫米)/.test(combined) ? 'mm' : 'cm';
    }

    // 其余参数保留（去掉已抽走的重量/尺寸项）
    const used = new Set([weightP, lenP, widP, heiP, dimP].filter(Boolean));
    const remaining = pairs.filter((p) => !used.has(p));

    return { weight: weightP?.value ?? '', dims: { l, w, h }, dimsUnit, remaining };
}

/** 调用页面里的采集入口，返回 ScanResult 或 null（未加载/不支持） */
async function scanTab(tabId: number): Promise<ScanResult | null> {
    try {
        const [r] = await chrome.scripting.executeScript({
            target: { tabId },
            func: () => (window as any).__SellerHelperOzon?.scan?.(),
        });
        return (r?.result as ScanResult) ?? null;
    } catch {
        return null;
    }
}

/** 判断当前 tab 是否 Ozon 商品详情页 */
async function isProductPage(tabId: number): Promise<boolean> {
    try {
        const [r] = await chrome.scripting.executeScript({
            target: { tabId },
            func: () =>
                /\/product\/[^/]+-\d+\/?/.test(location.pathname) ||
                /\/context\/detail\/id\/\d+/.test(location.pathname),
        });
        return !!r?.result;
    } catch {
        return false;
    }
}

function Panel() {
    const { message } = AntdApp.useApp();
    const { token } = theme.useToken();

    const [form] = Form.useForm();
    const [status, setStatus] = useState('');
    const [error, setError] = useState('');
    const [result, setResult] = useState<ScanResult | null>(null);
    const [selected, setSelected] = useState<Set<string>>(new Set());
    const [params, setParams] = useState<Array<{ key: string; value: string }>>([]);
    const [dimsUnit, setDimsUnit] = useState<'mm' | 'cm'>('cm');
    const [folderName, setFolderName] = useState('');
    const [rootLabel, setRootLabel] = useState('');
    const [exporting, setExporting] = useState(false);
    const [uploading, setUploading] = useState(false);
    const [exportResult, setExportResult] = useState<ExportResult | null>(null);
    const [uploadResult, setUploadResult] = useState<{ product_id: string; stage: string; assets_queued: number } | null>(null);

    // 服务端设置（上传用）
    const [settings, setSettings] = useState<BackendSettings | null>(null);
    const [baseUrl, setBaseUrl] = useState('http://127.0.0.1:8800');
    const [appToken, setAppToken] = useState('');

    useEffect(() => {
        loadRootDir().then((h) => setRootLabel(h ? h.name : ''));
        loadSettings().then((s) => {
            setSettings(s);
            setBaseUrl(s.baseUrl);
            setAppToken(s.token);
        });
    }, []);

    const groups = useMemo(() => {
        if (!result) return [];
        return GROUP_ORDER.map((g) => ({
            ...g,
            items: result.images.filter((img) => img.groupKey === g.key),
        })).filter((g) => g.items.length > 0);
    }, [result]);

    const selectedCount = useMemo(() => {
        if (!result) return 0;
        return result.images.filter((img) => selected.has(img.key)).length;
    }, [result, selected]);

    const onSaveSettings = async () => {
        const s: BackendSettings = { baseUrl: baseUrl.trim(), token: appToken.trim() };
        await saveSettings(s);
        setSettings(s);
        message.success('服务端设置已保存');
    };

    const handleScan = async () => {
        setError('');
        setResult(null);
        setExportResult(null);
        setUploadResult(null);
        setStatus('采集中');

        try {
            const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
            if (!tab?.id) {
                setError('无法获取当前标签页');
                setStatus('');
                return;
            }

            let data = await scanTab(tab.id);

            // 内容脚本没加载（页面在插件安装/重载前就打开了）→ 手动注入后重试
            if (!data) {
                try {
                    await chrome.scripting.executeScript({
                        target: { tabId: tab.id },
                        files: ['content-scripts/content.js'],
                    });
                    await new Promise((r) => setTimeout(r, 300));
                    data = await scanTab(tab.id);
                } catch {
                    /* 注入失败忽略，走下方错误提示 */
                }
            }

            if (!data) {
                const isProduct = await isProductPage(tab.id);
                setError(
                    isProduct
                        ? '采集失败：内容脚本未生效，请刷新商品页后重试'
                        : '当前页面不是 Ozon 商品详情页，请打开一个商品页后再采集',
                );
                setStatus('');
                return;
            }

            setResult(data);
            setSelected(defaultSelection(data));
            setFolderName(cleanFilename(data.texts.find((t) => t.kind === 'title')?.content ?? '') || '');
            const rawParams = data.texts.find((t) => t.kind === 'params')?.pairs ?? [];
            const { weight, dims, dimsUnit: du, remaining } = extractWeightAndDims(rawParams);
            setParams(remaining);
            setDimsUnit(du);
            // 填表单
            form.setFieldsValue({
                title: data.texts.find((t) => t.kind === 'title')?.content ?? '',
                price: data.texts.find((t) => t.kind === 'price')?.content ?? '',
                brand: data.texts.find((t) => t.kind === 'brand')?.content || '无品牌',
                sellingPoints: data.texts.find((t) => t.kind === 'selling_point')?.content ?? '',
                desc: data.texts.find((t) => t.kind === 'desc')?.content ?? '',
                packWeight: weight,
                packLen: dims.l,
                packWidth: dims.w,
                packHeight: dims.h,
            });
            setStatus('采集完成');
        } catch (err) {
            setError(`采集失败: ${err instanceof Error ? err.message : String(err)}`);
            setStatus('');
        }
    };

    const handlePickDir = async () => {
        setError('');
        try {
            // 始终弹选择器（选择或更换目录）
            const handle = await chooseRootDir();
            setRootLabel(handle.name);
            message.success(`已选择目录「${handle.name}」`);
        } catch (err) {
            // 用户取消选择（AbortError）不算错误，静默处理
            if (err instanceof DOMException && err.name === 'AbortError') {
                return;
            }
            setError(`选择目录失败: ${err instanceof Error ? err.message : String(err)}`);
        }
    };

    const toggleOne = (key: string) => {
        setSelected((prev) => {
            const next = new Set(prev);
            if (next.has(key)) next.delete(key);
            else next.add(key);
            return next;
        });
    };

    const toggleGroup = (items: ImageMaterial[]) => {
        setSelected((prev) => {
            const next = new Set(prev);
            const allOn = items.every((i) => next.has(i.key));
            for (const i of items) {
                if (allOn) next.delete(i.key);
                else next.add(i.key);
            }
            return next;
        });
    };

    const getEdits = (): TextEdits => {
        const v = form.getFieldsValue();
        return {
            title: v.title,
            price: v.price,
            brand: v.brand,
            sellingPoints: v.sellingPoints,
            desc: v.desc,
            params,
            weight: v.packWeight,
            dims: { l: v.packLen, w: v.packWidth, h: v.packHeight },
            dimsUnit,
        };
    };

    const handleExport = async () => {
        if (!result) return;
        if (selectedCount === 0) {
            setError('请至少勾选一张图片');
            return;
        }
        setExporting(true);
        setError('');
        setExportResult(null);
        try {
            const name = folderName.trim() || `ozon-${result.itemId ?? 'product'}`;
            const built = buildProduct(result, selected, getEdits());
            const res = await writeProductFolder(name, built.product, built.sources, built.files);
            setExportResult(res);
            message.success('已导出到本地');
        } catch (err) {
            setError(`导出失败: ${err instanceof Error ? err.message : String(err)}`);
        } finally {
            setExporting(false);
        }
    };

    const handleUpload = async () => {
        if (!result) return;
        if (selectedCount === 0) {
            setError('请至少勾选一张图片');
            return;
        }
        setUploading(true);
        setError('');
        setUploadResult(null);
        try {
            const payload = buildMaterialsPayload(result, selected, getEdits());
            const resp = await chrome.runtime.sendMessage({
                action: 'uploadMaterials',
                baseUrl: settings?.baseUrl ?? 'http://127.0.0.1:8800',
                token: settings?.token ?? '',
                payload,
            });
            if (!resp?.ok) throw new Error(resp?.error ?? '上传失败');
            setUploadResult(resp.data);
            message.success('已上传服务端，进入采集箱');
        } catch (err) {
            setError(`上传失败: ${err instanceof Error ? err.message : String(err)}`);
        } finally {
            setUploading(false);
        }
    };

    return (
        <div style={{ minHeight: '100vh' }}>
            {/* 顶部固定：标题 + 采集按钮 */}
            <div style={{ position: 'sticky', top: 0, zIndex: 20, background: '#f5f5f5', padding: '12px 12px 8px', borderBottom: '1px solid #f0f0f0' }}>
                <div style={{ marginBottom: 8 }}>
                    <Title level={4} style={{ margin: 0 }}>
                        🪆 套娃采集助手
                    </Title>
                    <Text type="secondary" style={{ fontSize: 12 }}>
                        采集 Ozon 商品页 · 导出到本地或上传服务端
                    </Text>
                </div>

                {/* 采集按钮 */}
                <Button
                    type="primary"
                    block
                    size="large"
                    icon={<ScanOutlined />}
                    loading={status === '采集中'}
                    onClick={handleScan}
                >
                    {status === '采集中' ? '采集中…' : '开始采集当前页'}
                </Button>
            </div>

            <div style={{ padding: '0 12px 12px' }}>

            {/* 服务端设置 */}
            <Collapse
                ghost
                size="small"
                style={{ marginTop: 8 }}
                items={[
                    {
                        key: 'settings',
                        label: (
                            <Space size={4}>
                                <SettingOutlined />
                                <span style={{ fontSize: 12 }}>服务端设置（上传用）</span>
                            </Space>
                        ),
                        children: (
                            <div>
                                <div style={{ marginBottom: 8 }}>
                                    <Text style={{ fontSize: 12 }}>后端地址</Text>
                                    <Input
                                        value={baseUrl}
                                        onChange={(e) => setBaseUrl(e.target.value)}
                                        placeholder="http://127.0.0.1:8800"
                                    />
                                </div>
                                <div style={{ marginBottom: 8 }}>
                                    <Text style={{ fontSize: 12 }}>访问 Token（可选，留空即可）</Text>
                                    <Input.Password
                                        value={appToken}
                                        onChange={(e) => setAppToken(e.target.value)}
                                        placeholder="后续加账户体系时再填"
                                    />
                                </div>
                                <Button size="small" onClick={onSaveSettings}>
                                    保存设置
                                </Button>
                            </div>
                        ),
                    },
                ]}
            />

            {error && <Alert type="error" showIcon message={error} style={{ marginTop: 8 }} />}

            {result && (
                <>
                    <Card size="small" style={{ marginTop: 12 }} title="采集信息（可修改）">
                        <div style={{ marginBottom: 8 }}>
                            <Space wrap size={4}>
                                <Tag color="purple">{result.platform.toUpperCase()}</Tag>
                                {result.itemId && <Tag>{result.itemId}</Tag>}
                                <Tag color="blue">来源:{result.source}</Tag>
                            </Space>
                        </div>

                        <Form form={form} layout="vertical" size="small">
                            <Form.Item label="标题" name="title">
                                <Input.TextArea autoSize={{ minRows: 2, maxRows: 4 }} />
                            </Form.Item>
                            <Row gutter={8}>
                                <Col span={12}>
                                    <Form.Item label="价格" name="price">
                                        <Input />
                                    </Form.Item>
                                </Col>
                                <Col span={12}>
                                    <Form.Item label="品牌" name="brand">
                                        <Input />
                                    </Form.Item>
                                </Col>
                            </Row>
                            <Form.Item label="包装重量" name="packWeight">
                                <Input placeholder="如 3.5 кг" />
                            </Form.Item>
                            <Form.Item label="包装尺寸（长 × 宽 × 高）">
                                <Space.Compact block>
                                    <Form.Item name="packLen" noStyle>
                                        <Input placeholder="长" />
                                    </Form.Item>
                                    <Form.Item name="packWidth" noStyle>
                                        <Input placeholder="宽" />
                                    </Form.Item>
                                    <Form.Item name="packHeight" noStyle>
                                        <Input placeholder="高" />
                                    </Form.Item>
                                </Space.Compact>
                            </Form.Item>
                            <Form.Item label="卖点" name="sellingPoints">
                                <Input.TextArea autoSize={{ minRows: 2, maxRows: 4 }} />
                            </Form.Item>
                            <Form.Item label="描述" name="desc">
                                <Input.TextArea autoSize={{ minRows: 3, maxRows: 8 }} />
                            </Form.Item>

                            {/* 参数表（左侧参数名只读，右侧参数值可编辑） */}
                            {params.length > 0 && (
                                <Collapse
                                    ghost
                                    size="small"
                                    items={[
                                        {
                                            key: 'params',
                                            label: <Text style={{ fontSize: 12 }}>参数表（{params.length} 项）</Text>,
                                            children: (
                                                <div>
                                                    {params.map((p, i) => (
                                                        <Row key={i} gutter={8} align="middle" style={{ marginBottom: 6 }}>
                                                            <Col span={10}>
                                                                <Text type="secondary" style={{ fontSize: 12, wordBreak: 'break-all', display: 'block' }}>
                                                                    {p.key || '—'}
                                                                </Text>
                                                            </Col>
                                                            <Col span={14}>
                                                                <Input
                                                                    size="small"
                                                                    value={p.value}
                                                                    onChange={(e) => {
                                                                        const next = [...params];
                                                                        next[i] = { ...next[i], value: e.target.value };
                                                                        setParams(next);
                                                                    }}
                                                                />
                                                            </Col>
                                                        </Row>
                                                    ))}
                                                </div>
                                            ),
                                        },
                                    ]}
                                />
                            )}
                        </Form>
                    </Card>

                    {/* 图片分组 */}
                    <Card size="small" style={{ marginTop: 12 }} title={`图片素材（已选 ${selectedCount} 张）`}>
                        {groups.map((g) => {
                            const allOn = g.items.every((i) => selected.has(i.key));
                            return (
                                <div key={g.key} style={{ marginBottom: 12 }}>
                                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
                                        <Text strong style={{ fontSize: 12 }}>
                                            {g.name} ({g.items.length})
                                        </Text>
                                        <a style={{ fontSize: 12 }} onClick={() => toggleGroup(g.items)}>
                                            {allOn ? '取消全选' : '全选'}
                                        </a>
                                    </div>
                                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                                        {g.items.map((img) => {
                                            const on = selected.has(img.key);
                                            return (
                                                <div
                                                    key={img.key}
                                                    onClick={() => toggleOne(img.key)}
                                                    style={{
                                                        position: 'relative',
                                                        width: 64,
                                                        height: 64,
                                                        border: on ? `2px solid ${token.colorPrimary}` : '1px solid #e0e0e0',
                                                        borderRadius: 8,
                                                        overflow: 'hidden',
                                                        cursor: 'pointer',
                                                        background: '#f5f5f5',
                                                    }}
                                                >
                                                    {img.type === 'video' ? (
                                                        <div style={{ position: 'relative', width: '100%', height: '100%', background: '#eee' }}>
                                                            {img.thumbUrl && !/\.(mp4|webm|m3u8|mov|avi)(\?|$)/i.test(img.thumbUrl) ? (
                                                                <img src={img.thumbUrl} alt="视频封面" style={{ width: '100%', height: '100%', objectFit: 'cover' }} loading="lazy" />
                                                            ) : null}
                                                            <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(0,0,0,0.25)' }}>
                                                                <span style={{ color: '#fff', fontSize: 20, lineHeight: 1 }}>▶</span>
                                                            </div>
                                                        </div>
                                                    ) : (
                                                        <img src={img.thumbUrl} alt={img.variantName ?? g.name} style={{ width: '100%', height: '100%', objectFit: 'cover' }} loading="lazy" />
                                                    )}
                                                    {on && (
                                                        <div style={{ position: 'absolute', inset: 0, background: `rgba(139,92,246,0.15)` }}>
                                                            <span style={{ position: 'absolute', top: 2, right: 5, color: token.colorPrimary, fontSize: 14 }}>✓</span>
                                                        </div>
                                                    )}
                                                    {img.variantName && (
                                                        <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, background: 'rgba(0,0,0,0.5)', color: '#fff', fontSize: 9, padding: '1px 2px', textAlign: 'center', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                                                            {img.variantName}
                                                        </div>
                                                    )}
                                                </div>
                                            );
                                        })}
                                    </div>
                                </div>
                            );
                        })}
                    </Card>

                    {/* 警告 */}
                    {result.warnings.length > 0 && (
                        <div style={{ marginTop: 12 }}>
                            {result.warnings.map((w, i) => (
                                <Alert key={i} type="warning" showIcon message={w} style={{ marginBottom: 4 }} />
                            ))}
                        </div>
                    )}

                    <div style={{ position: 'sticky', bottom: 0, background: '#f5f5f5', padding: '12px 0', zIndex: 10, marginTop: 12, borderTop: '1px solid #f0f0f0' }}>
                    {/* 本地文件夹名 + 导出/上传（固定在底部） */}
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
                        <Text style={{ fontSize: 12, whiteSpace: 'nowrap' }}>本地文件夹名</Text>
                        <Input
                            value={folderName}
                            onChange={(e) => setFolderName(e.target.value)}
                            placeholder="留空用商品标题"
                            size="small"
                        />
                    </div>
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
                        <div style={{ fontSize: 11, color: '#888', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                            {rootLabel ? `保存到：${rootLabel}` : '未选择保存目录'}
                        </div>
                        <Button size="small" onClick={handlePickDir}>
                            {rootLabel ? '更换目录' : '选择目录'}
                        </Button>
                    </div>

                    <Row gutter={8}>
                        <Col span={12}>
                            <Button
                                block
                                icon={<DownloadOutlined />}
                                onClick={handleExport}
                                loading={exporting}
                                disabled={selectedCount === 0}
                            >
                                导出到本地
                            </Button>
                        </Col>
                        <Col span={12}>
                            <Button
                                block
                                type="primary"
                                icon={<CloudUploadOutlined />}
                                onClick={handleUpload}
                                loading={uploading}
                                disabled={selectedCount === 0}
                            >
                                上传服务端
                            </Button>
                        </Col>
                    </Row>

                    {exportResult && (
                        <Alert
                            type={exportResult.failed.length ? 'warning' : 'success'}
                            showIcon
                            style={{ marginTop: 8 }}
                            message={`已写入 ${exportResult.written} 张图片到「${exportResult.folderName}」${exportResult.failed.length ? `，${exportResult.failed.length} 张失败` : ''}`}
                        />
                    )}
                    {uploadResult && (
                        <Alert
                            type="success"
                            showIcon
                            style={{ marginTop: 8 }}
                            message={`已上传服务端，商品已进入采集箱（素材 ${uploadResult.assets_queued} 张，后台转存中）`}
                        />
                    )}
                    </div>
                </>
            )}

            {!result && (
                <div style={{ marginTop: 16, padding: 12, background: '#fafafa', borderRadius: 8, fontSize: 12, color: '#888' }}>
                    <div>💡 使用说明：</div>
                    <ol style={{ margin: '4px 0 0 18px', padding: 0 }}>
                        <li>打开 Ozon 商品详情页（ru/kz/by）</li>
                        <li>滚动到页面底部（加载详情图）</li>
                        <li>点「开始采集」→ 核对/修改信息 → 导出或上传</li>
                    </ol>
                </div>
            )}
            </div>
        </div>
    );
}

function Root() {
    return (
        <ConfigProvider
            locale={zhCN}
            theme={{
                token: {
                    colorPrimary: '#8b5cf6',
                    borderRadius: 8,
                },
            }}
        >
            <AntdApp>
                <Panel />
            </AntdApp>
        </ConfigProvider>
    );
}

const root = createRoot(document.getElementById('root')!);
root.render(<Root />);

export default Root;
