import { useState, useCallback, useRef, useMemo } from 'react';
import {
    getPortfolio, addPortfolio, updatePortfolio, deletePortfolio,
    upsertCash, deleteCash,
} from '../../../api';
import { emptyPortfolioForm, computeBrokerSummary } from '../stockUtils';

export default function usePortfolio() {
    const [portfolio, setPortfolio] = useState(null);
    const [portfolioLoading, setPortfolioLoading] = useState(false);
    const [portfolioError, setPortfolioError] = useState('');
    const [portfolioLoaded, setPortfolioLoaded] = useState(false);

    /* add form */
    const [addForm, setAddForm] = useState({ ...emptyPortfolioForm });
    const [addFormOpen, setAddFormOpen] = useState(false);
    const [addLoading, setAddLoading] = useState(false);
    const [addError, setAddError] = useState('');

    /* edit */
    const [editingId, setEditingId] = useState(null);
    const [editForm, setEditForm] = useState({});
    const [editLoading, setEditLoading] = useState(false);
    const editOrigRef = useRef({});

    /* delete / sell confirm */
    const [deleteConfirmId, setDeleteConfirmId] = useState(null);
    const [sellConfirmId, setSellConfirmId] = useState(null);
    const [sellLoading, setSellLoading] = useState(false);

    /* cash */
    const [cashForm, setCashForm] = useState({ broker: '', cash: '' });
    const [cashSaving, setCashSaving] = useState(false);
    const [cashError, setCashError] = useState('');
    const [cashEditingBroker, setCashEditingBroker] = useState(null);
    const [cashEditingValue, setCashEditingValue] = useState('');
    const [cashEditSaving, setCashEditSaving] = useState(false);

    /* derived */
    const portfolioHoldings = portfolio?.holdings ?? [];
    // 총 매입은 "각 종목 매입가의 단순 합(수량 미곱산)"으로 표시 (박재오 정의).
    // 백엔드 summary.total_buy(매입가×수량)는 무시하고 프론트에서 재계산해
    // 요약카드·증권사별·AI 프롬프트가 모두 같은 값을 쓰도록 통일.
    const portfolioSummary = portfolioHoldings.length
        ? { ...(portfolio?.summary ?? {}), total_buy: computeBrokerSummary(portfolioHoldings).totalBuy }
        : (portfolio?.summary ?? {});
    const cashList = portfolio?.cash ?? [];
    const totalCash = portfolioSummary.total_cash ?? null;
    const totalAssets = portfolioSummary.total_assets ?? null;

    const brokerGroups = useMemo(() => {
        const map = {};
        for (const item of portfolioHoldings) {
            const broker = item.broker || '기타';
            if (!map[broker]) map[broker] = [];
            map[broker].push(item);
        }
        return Object.entries(map).sort(([a], [b]) => a.localeCompare(b));
    }, [portfolioHoldings]);

    const brokerColors = useMemo(() => {
        const palette = [
            { border: 'rgba(129,140,248,0.5)', bg: 'rgba(129,140,248,0.06)' },
            { border: 'rgba(251,191,36,0.5)', bg: 'rgba(251,191,36,0.06)' },
            { border: 'rgba(52,211,153,0.5)', bg: 'rgba(52,211,153,0.06)' },
            { border: 'rgba(244,114,182,0.5)', bg: 'rgba(244,114,182,0.06)' },
            { border: 'rgba(251,146,60,0.5)', bg: 'rgba(251,146,60,0.06)' },
            { border: 'rgba(139,92,246,0.5)', bg: 'rgba(139,92,246,0.06)' },
        ];
        const map = {};
        brokerGroups.forEach(([broker], i) => {
            map[broker] = palette[i % palette.length];
        });
        return map;
    }, [brokerGroups]);

    const getBrokerSummary = computeBrokerSummary;

    /* loaders */
    const loadPortfolio = useCallback(async () => {
        setPortfolioLoading(true);
        setPortfolioError('');
        try {
            const data = await getPortfolio();
            setPortfolio(data);
            setPortfolioLoaded(true);
        } catch (err) {
            setPortfolioError(err?.message ?? String(err));
        } finally {
            setPortfolioLoading(false);
        }
    }, []);

    /* actions */
    const handleAddSubmit = async (e) => {
        e.preventDefault();
        setAddLoading(true);
        setAddError('');
        try {
            await addPortfolio({
                broker: addForm.broker.trim(),
                ticker: addForm.ticker.trim(),
                name: addForm.name.trim(),
                quantity: Number(addForm.quantity),
                avg_price: Number(addForm.avg_price),
                purchase_price: addForm.purchase_price === '' || addForm.purchase_price == null
                    ? Number(addForm.avg_price)
                    : Number(addForm.purchase_price),
            });
            setAddForm({ ...emptyPortfolioForm });
            setAddFormOpen(false);
            await loadPortfolio();
        } catch (err) {
            setAddError(err?.message ?? String(err));
        } finally {
            setAddLoading(false);
        }
    };

    const handleEditStart = (item) => {
        setEditingId(item.id);
        const data = {
            quantity: item.quantity,
            avg_price: item.avg_price,
            purchase_price: item.purchase_price ?? item.avg_price,
            broker: item.broker,
            name: item.name,
        };
        setEditForm(data);
        editOrigRef.current = { ...data };
    };

    const handleEditSave = async (id) => {
        setEditLoading(true);
        try {
            const orig = editOrigRef.current ?? {};
            const diff = {};
            for (const key of Object.keys(editForm)) {
                if (editForm[key] !== orig[key]) diff[key] = editForm[key];
            }
            if (Object.keys(diff).length === 0) { setEditingId(null); return; }
            await updatePortfolio(id, diff);
            setEditingId(null);
            await loadPortfolio();
        } catch (err) {
            const msg = err?.message ?? String(err);
            if (msg.includes('404') || msg.includes('not found')) {
                alert('해당 종목을 찾을 수 없습니다. 이미 삭제되었을 수 있습니다.');
                await loadPortfolio();
            } else {
                alert('수정 실패: ' + msg);
            }
        } finally {
            setEditLoading(false);
        }
    };

    const handleDelete = async (id) => {
        try {
            await deletePortfolio(id);
            setDeleteConfirmId(null);
            await loadPortfolio();
        } catch (err) {
            const msg = err?.message ?? String(err);
            if (msg.includes('404') || msg.includes('not found')) {
                alert('해당 종목을 찾을 수 없습니다. 이미 삭제되었을 수 있습니다.');
                setDeleteConfirmId(null);
                await loadPortfolio();
            } else {
                alert('삭제 실패: ' + msg);
            }
        }
    };

    /* cash actions */
    const handleCashSave = async (e) => {
        e.preventDefault();
        if (!cashForm.broker.trim() || cashForm.cash === '') return;
        setCashSaving(true);
        setCashError('');
        try {
            await upsertCash(cashForm.broker.trim(), Number(cashForm.cash));
            setCashForm({ broker: '', cash: '' });
            await loadPortfolio();
        } catch (err) {
            setCashError(err?.message ?? String(err));
        } finally {
            setCashSaving(false);
        }
    };

    const handleCashDelete = async (broker) => {
        try {
            await deleteCash(broker);
            await loadPortfolio();
        } catch (err) {
            alert('예수금 삭제 실패: ' + (err?.message ?? String(err)));
        }
    };

    const handleCashInlineEdit = (item) => {
        setCashEditingBroker(item.broker);
        setCashEditingValue(String(item.cash ?? ''));
    };

    const handleCashInlineSave = async (broker) => {
        if (cashEditingValue === '') return;
        setCashEditSaving(true);
        try {
            await upsertCash(broker, Number(cashEditingValue));
            setCashEditingBroker(null);
            setCashEditingValue('');
            await loadPortfolio();
        } catch (err) {
            alert('예수금 수정 실패: ' + (err?.message ?? String(err)));
        } finally {
            setCashEditSaving(false);
        }
    };

    const handleCashInlineCancel = () => {
        setCashEditingBroker(null);
        setCashEditingValue('');
    };

    /* sell (현재가 매도) */
    const handleSell = async (item, { cashList: cl, loadSellHistoryAfter }) => {
        const sellPrice = item.current_price ?? item.avg_price;
        const avgPrice = item.avg_price ?? 0;
        const qty = item.quantity ?? 0;
        const saleAmount = sellPrice * qty;
        const buyAmount = avgPrice * qty;
        const realizedProfit = saleAmount - buyAmount;
        const realizedRate = buyAmount > 0 ? (realizedProfit / buyAmount) * 100 : 0;
        const broker = item.broker ?? '';

        setSellLoading(true);
        try {
            const existing = cl.find((c) => c.broker === broker);
            const newCash = (existing?.cash ?? 0) + saleAmount;
            await upsertCash(broker, newCash);
            await deletePortfolio(item.id);
            setSellConfirmId(null);
            await loadPortfolio();
            if (loadSellHistoryAfter) {
                await loadSellHistoryAfter({
                    broker, ticker: item.ticker ?? '', name: item.name ?? item.ticker ?? 'N/A',
                    quantity: qty, avg_price: avgPrice, sell_price: sellPrice,
                    buy_amount: buyAmount, sell_amount: saleAmount,
                    realized_profit: realizedProfit, realized_rate: realizedRate,
                    sold_at: new Date().toISOString(),
                });
            }
        } catch (err) {
            alert('매도 처리 실패: ' + (err?.message ?? String(err)));
        } finally {
            setSellLoading(false);
        }
    };

    return {
        portfolio, portfolioLoading, portfolioError, portfolioLoaded, loadPortfolio,
        portfolioHoldings, portfolioSummary, cashList, totalCash, totalAssets,
        addForm, setAddForm, addFormOpen, setAddFormOpen, addLoading, addError, handleAddSubmit,
        editingId, setEditingId, editForm, setEditForm, editLoading, handleEditStart, handleEditSave,
        deleteConfirmId, setDeleteConfirmId, handleDelete,
        sellConfirmId, setSellConfirmId, sellLoading, handleSell,
        cashForm, setCashForm, cashSaving, cashError, handleCashSave, handleCashDelete,
        cashEditingBroker, cashEditingValue, setCashEditingValue, cashEditSaving,
        handleCashInlineEdit, handleCashInlineSave, handleCashInlineCancel,
        brokerGroups, brokerColors, getBrokerSummary,
    };
}
