package com.bsphp.login;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.function.Consumer;

/**
 * 对齐 Mac {@code CardMainControlPanelView}：登录成功后的主控制面板。
 */
final class ControlPanelDialog extends JDialog {

    private final CardBSPHPClient client;
    private final String loggedCardId;
    private final Consumer<Void> onSessionEnd;

    private final JLabel vipLabel;
    private final JPasswordField auxPwd = new JPasswordField(24);
    private final JTextArea detail = new JTextArea(5, 52);
    private volatile boolean busy;

    ControlPanelDialog(JFrame owner, CardBSPHPClient client, String loggedCardId, String initialVipExpiry,
                       Consumer<Void> onSessionEnd) {
        super(owner, "主控制面板", false);
        this.client = client;
        this.loggedCardId = loggedCardId;
        this.onSessionEnd = onSessionEnd;
        this.vipLabel = new JLabel(initialVipExpiry != null && !initialVipExpiry.isEmpty() ? initialVipExpiry : "-");

        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLayout(new BorderLayout(8, 8));

        JPanel scrollInner = new JPanel();
        scrollInner.setLayout(new BoxLayout(scrollInner, BoxLayout.Y_AXIS));
        scrollInner.setBorder(BorderFactory.createEmptyBorder(8, 10, 8, 10));

        scrollInner.add(line("当前卡号：" + loggedCardId));
        scrollInner.add(line("VIP 到期："));
        scrollInner.add(vipLabel);
        scrollInner.add(Box.createVerticalStrut(10));

        scrollInner.add(section("常用接口"));
        scrollInner.add(row4(
                act("刷新到期", true, client::getDateIC),
                act("登录状态", client::getLoginInfo),
                act("心跳", client::heartbeat),
                act("公告", client::getNotice)));
        scrollInner.add(row4(
                act("服务器时间", client::getServerDate),
                act("版本", client::getVersion),
                act("软件描述", client::getSoftInfo),
                act("预设URL", client::getPresetURL)));
        scrollInner.add(flow(act("Web地址", client::getWebURL)));

        scrollInner.add(section("自定义配置模型"));
        scrollInner.add(row3(
                act("软件配置", () -> client.getAppCustom("myapp")),
                act("VIP配置", () -> client.getAppCustom("myvip")),
                act("登录配置", () -> client.getAppCustom("mylogin"))));

        scrollInner.add(section("公共函数"));
        scrollInner.add(row4(
                act("全局配置", client::getGlobalInfo),
                act("逻辑A", client::getLogicA),
                act("逻辑B", client::getLogicB),
                act("激活查询", () -> client.queryCard(loggedCardId))));
        scrollInner.add(flow(act("卡信息示例", () -> {
            String pwd = new String(auxPwd.getPassword());
            return client.getCardInfo(loggedCardId, pwd, "UserName");
        })));

        scrollInner.add(Box.createVerticalStrut(8));
        scrollInner.add(line("卡密（解绑、绑定本机、卡信息 等需要时填写）"));
        JPanel aux = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 0));
        aux.add(new JLabel("可选：卡密码"));
        aux.add(auxPwd);
        scrollInner.add(aux);

        scrollInner.add(flow(
                act("绑定本机", () -> client.bindCard(CardBSPHPClient.machineCode(), loggedCardId, new String(auxPwd.getPassword()))),
                act("解除绑定", () -> client.unbindCard(loggedCardId, new String(auxPwd.getPassword())))));

        scrollInner.add(section("后台页面"));
        scrollInner.add(flow(
                saleBtn("续费充值", SaleWebUtil.renewUrlForUser(CardBSPHPConfig.RENEW_URL_BASE, loggedCardId)),
                saleBtn("购买充值卡", CardBSPHPConfig.GEN_URL),
                saleBtn("购买库存卡", CardBSPHPConfig.STOCK_URL)));

        JButton logout = new JButton("注销并返回登录");
        logout.addActionListener(e -> doLogout());
        scrollInner.add(Box.createVerticalStrut(8));
        scrollInner.add(flow(logout));

        JScrollPane sp = new JScrollPane(scrollInner);
        sp.setPreferredSize(new Dimension(580, 420));
        add(sp, BorderLayout.CENTER);

        detail.setEditable(false);
        detail.setLineWrap(true);
        detail.setWrapStyleWord(true);
        JScrollPane dsp = new JScrollPane(detail);
        dsp.setBorder(BorderFactory.createTitledBorder("接口返回"));
        dsp.setPreferredSize(new Dimension(580, 120));
        add(dsp, BorderLayout.SOUTH);

        pack();
        setLocationRelativeTo(owner);
        setMinimumSize(new Dimension(600, 520));
    }

    private static JLabel line(String t) {
        JLabel l = new JLabel(t);
        l.setAlignmentX(LEFT_ALIGNMENT);
        return l;
    }

    private static JLabel section(String t) {
        JLabel l = new JLabel(t);
        l.setFont(l.getFont().deriveFont(l.getFont().getSize() + 1f));
        l.setAlignmentX(LEFT_ALIGNMENT);
        return l;
    }

    private JPanel row4(JButton a, JButton b, JButton c, JButton d) {
        JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 4));
        p.setAlignmentX(LEFT_ALIGNMENT);
        p.add(a);
        p.add(b);
        p.add(c);
        p.add(d);
        return p;
    }

    private JPanel row3(JButton a, JButton b, JButton c) {
        JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 4));
        p.setAlignmentX(LEFT_ALIGNMENT);
        p.add(a);
        p.add(b);
        p.add(c);
        return p;
    }

    private JPanel flow(Component... cs) {
        JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 4));
        p.setAlignmentX(LEFT_ALIGNMENT);
        for (Component c : cs) p.add(c);
        return p;
    }

    private JButton saleBtn(String title, String url) {
        JButton b = new JButton(title);
        b.addActionListener(e -> SaleWebUtil.open(url));
        return b;
    }

    private JButton act(String title, ApiCall call) {
        return act(title, false, call);
    }

    private JButton act(String title, boolean refreshVip, ApiCall call) {
        JButton b = new JButton(title);
        b.addActionListener(e -> runApi(title, refreshVip, call, b));
        return b;
    }

    private void runApi(String title, boolean refreshVip, ApiCall call, JButton src) {
        if (busy || loggedCardId.isEmpty()) return;
        busy = true;
        src.setEnabled(false);
        new SwingWorker<BSPHPAPIResult, Void>() {
            @Override
            protected BSPHPAPIResult doInBackground() throws Exception {
                return call.get();
            }

            @Override
            protected void done() {
                src.setEnabled(true);
                try {
                    BSPHPAPIResult r = get();
                    if (refreshVip) {
                        String m = r.message();
                        if (m != null && !m.isEmpty()) {
                            vipLabel.setText(m);
                        }
                    }
                    String body = r.message();
                    if (body == null || body.isEmpty()) body = "（无 data 文本）";
                    detail.setText("[" + title + "] code=" + r.code + "\n" + body);
                } catch (Exception ex) {
                    detail.setText(ex.toString());
                } finally {
                    busy = false;
                }
            }
        }.execute();
    }

    private void doLogout() {
        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                client.logout();
                return null;
            }

            @Override
            protected void done() {
                onSessionEnd.accept(null);
                dispose();
            }
        }.execute();
    }

    @FunctionalInterface
    private interface ApiCall {
        BSPHPAPIResult get() throws Exception;
    }
}
