package com.bsphp.login;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.HeadlessException;

/**
 * 对齐 Mac {@code ContentView}：公告 + 卡密 Tab + 机器码 Tab。
 */
final class CardMainFrame extends JFrame {
    private static final Font UI_FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
    private static final int INPUT_HEIGHT = 32;
    private static final int BTN_HEIGHT = 32;
    private static final int ROW_GAP = 20;

    private final CardBSPHPClient client = new CardBSPHPClient(
            CardBSPHPConfig.URL,
            CardBSPHPConfig.MUTUAL_KEY,
            CardBSPHPConfig.SERVER_PRIVATE_KEY,
            CardBSPHPConfig.CLIENT_PUBLIC_KEY);

    private final JTextArea notice = new JTextArea(3, 40);
    private final JTextField cardInput = new JTextField(28);
    private final JTextField cardPwd = new JTextField(16);
    private final JTextField machineVerifyInput = new JTextField(28);
    private final JTextField machineRenewInput = new JTextField(28);
    private final JTextField mcCardPwd = new JTextField(16);
    private final JTextField mcCardId = new JTextField(16);
    private final JLabel status = new JLabel("待操作");

    private ControlPanelDialog controlPanel;

    CardMainFrame() throws HeadlessException {
        super("BSPHP 卡密演示 (bsphp.java.car)");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        notice.setEditable(false);
        notice.setLineWrap(true);
        notice.setWrapStyleWord(true);
        notice.setText("加载中...");

        JPanel root = new JPanel(new BorderLayout(6, 6));
        root.setBorder(BorderFactory.createEmptyBorder(8, 10, 8, 10));

        JPanel noticeWrap = new JPanel(new BorderLayout());
        noticeWrap.setBorder(BorderFactory.createTitledBorder("公告"));
        noticeWrap.add(new JScrollPane(notice), BorderLayout.CENTER);
        root.add(noticeWrap, BorderLayout.NORTH);

        JTabbedPane tabs = new JTabbedPane();
        tabs.addTab("制作卡密登陆模式", buildCardTab());
        tabs.addTab("一键注册机器码账号", buildMachineTab());
        root.add(tabs, BorderLayout.CENTER);

        JPanel south = new JPanel(new BorderLayout());
        south.add(status, BorderLayout.WEST);
        root.add(south, BorderLayout.SOUTH);

        setContentPane(root);
        pack();
        setLocationRelativeTo(null);
        setMinimumSize(new Dimension(860, 600));

        String mc = CardBSPHPClient.machineCode();
        machineVerifyInput.setText(mc);
        machineRenewInput.setText(mc);

        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() {
                try {
                    client.bootstrap();
                    BSPHPAPIResult n = client.getNotice();
                    String msg = n.message();
                    javax.swing.SwingUtilities.invokeLater(() ->
                            notice.setText(msg == null || msg.isEmpty() ? "暂无公告" : msg));
                } catch (Exception e) {
                    javax.swing.SwingUtilities.invokeLater(() -> {
                        notice.setText("初始化失败（见控制台）");
                        status.setText(String.valueOf(e.getMessage()));
                    });
                    e.printStackTrace();
                }
                return null;
            }
        }.execute();
    }

    private JPanel buildCardTab() {
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.setBorder(BorderFactory.createEmptyBorder(4, 6, 4, 6));

        p.add(wrapRow("卡串：", cardInput));
        p.add(wrapRow("密码：", cardPwd));

        JPanel row = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 2));
        row.add(mkBtn("验证使用", this::verifyCard));
        row.add(mkBtn("网络测试", this::testNet));
        row.add(mkBtn("版本检测", this::checkVersion));
        row.add(mkBtn("续费充值", () -> SaleWebUtil.open(SaleWebUtil.renewUrlForUser(CardBSPHPConfig.RENEW_URL_BASE, cardInput.getText().trim()))));
        row.add(mkBtn("购买充值卡", () -> SaleWebUtil.open(CardBSPHPConfig.GEN_URL)));
        row.add(mkBtn("购买库存卡", () -> SaleWebUtil.open(CardBSPHPConfig.STOCK_URL)));
        p.add(row);
        p.add(status);
        return p;
    }

    private JPanel buildMachineTab() {
        JPanel p = new JPanel(new BorderLayout(6, 6));
        p.setBorder(BorderFactory.createEmptyBorder(4, 6, 4, 6));

        JLabel hint = new JLabel("机器码直接注册做卡号模式（账号就是机器码）");
        hint.setFont(UI_FONT);
        hint.setForeground(hint.getForeground().darker());

        JTabbedPane inner = new JTabbedPane();
        inner.addTab("机器码验证使用", buildMachineVerify());
        inner.addTab("机器码充值续费", buildMachineRenew());
        p.add(hint, BorderLayout.NORTH);
        p.add(inner, BorderLayout.CENTER);
        return p;
    }

    private JPanel buildMachineVerify() {
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        p.add(wrapRow("机器码：", machineVerifyInput));
        JPanel row = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 2));
        row.add(mkBtn("验证使用", this::verifyMachineAccount));
        row.add(mkBtn("网络测试", this::testNet));
        row.add(mkBtn("版本检测", this::checkVersion));
        p.add(row);
        return p;
    }

    private JPanel buildMachineRenew() {
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        p.add(wrapRow("机器码：", machineRenewInput));
        p.add(wrapRow("充值卡号：", mcCardPwd));
        p.add(wrapRow("充值密码：", mcCardId));
        JPanel row = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 2));
        JButton recharge = new JButton("确认充值");
        recharge.setFont(UI_FONT);
        recharge.setPreferredSize(new Dimension(96, BTN_HEIGHT));
        recharge.addActionListener(e -> activate());
        row.add(recharge);
        row.add(mkBtn("一键支付续费充值", () -> SaleWebUtil.open(SaleWebUtil.renewUrlForUser(CardBSPHPConfig.RENEW_URL_BASE, machineRenewInput.getText().trim()))));
        row.add(mkBtn("购买充值卡", () -> SaleWebUtil.open(CardBSPHPConfig.GEN_URL)));
        row.add(mkBtn("购买库存卡", () -> SaleWebUtil.open(CardBSPHPConfig.STOCK_URL)));
        p.add(row);
        return p;
    }

    private JPanel wrapRow(String label, JTextField field) {
        JPanel row = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 0));
        JLabel l = new JLabel(label);
        l.setFont(UI_FONT);
        l.setPreferredSize(new Dimension(82, 18));
        styleInput(field);
        row.add(l);
        row.add(field);
        row.setBorder(BorderFactory.createEmptyBorder(0, 0, ROW_GAP, 0));
        row.setMaximumSize(new Dimension(Integer.MAX_VALUE, INPUT_HEIGHT + ROW_GAP));
        return row;
    }

    private JButton mkBtn(String title, Runnable r) {
        JButton b = new JButton(title);
        b.setFont(UI_FONT);
        b.setPreferredSize(new Dimension(96, BTN_HEIGHT));
        b.addActionListener(e -> r.run());
        return b;
    }

    private void styleInput(JTextField tf) {
        tf.setFont(UI_FONT);
        Dimension d = tf.getPreferredSize();
        tf.setPreferredSize(new Dimension(Math.max(d.width, 110), INPUT_HEIGHT));
    }

    private void verifyCard() {
        String id = cardInput.getText().trim();
        if (id.isEmpty()) {
            status.setText("请输入卡串");
            return;
        }
        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                BSPHPAPIResult r = client.loginIC(id, cardPwd.getText(), null, null);
                String msg = r.message();
                if (msg == null || msg.isEmpty()) msg = "验证失败";
                final String fm = msg;
                javax.swing.SwingUtilities.invokeLater(() -> status.setText(fm));
                boolean ok = (r.code != null && r.code == 1081) || fm.contains("1081");
                if (!ok) return null;
                BSPHPAPIResult exp = client.getDateIC();
                String expDisplay = exp.message();
                if (expDisplay == null || expDisplay.isEmpty()) expDisplay = "-";
                final String expF = expDisplay;
                javax.swing.SwingUtilities.invokeLater(() -> openPanel(id, expF, fm));
                return null;
            }
        }.execute();
    }

    private void verifyMachineAccount() {
        String id = machineVerifyInput.getText().trim();
        if (id.isEmpty()) {
            status.setText("【机器码】请输入机器码（账号）");
            return;
        }
        String global = CardBSPHPClient.machineCode();
        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                BSPHPAPIResult feat = client.addCardFeatures(id, global, global);
                String featMsg = feat.message();
                if (featMsg == null || featMsg.isEmpty()) featMsg = "（无 data）";
                final String featMsgF = featMsg;
                javax.swing.SwingUtilities.invokeLater(() -> status.setText("[AddCardFeatures.key.ic] code=" + feat.code + " " + featMsgF));
                boolean featOk = (feat.code != null && (feat.code == 1011 || feat.code == 1081))
                        || featMsgF.contains("1081")
                        || featMsgF.contains("成功");
                if (!featOk) return null;

                BSPHPAPIResult r = client.loginIC(id, "", global, global);
                String msg = r.message();
                if (msg == null || msg.isEmpty()) msg = "验证失败";
                final String fm = msg;
                javax.swing.SwingUtilities.invokeLater(() -> status.setText("[login.ic] " + fm));
                boolean ok = (r.code != null && r.code == 1081) || fm.contains("1081");
                if (!ok) return null;
                BSPHPAPIResult exp = client.getDateIC();
                String expDisplay = exp.message();
                if (expDisplay == null || expDisplay.isEmpty()) expDisplay = "-";
                final String expF = expDisplay;
                javax.swing.SwingUtilities.invokeLater(() -> openPanel(id, expF, fm));
                return null;
            }
        }.execute();
    }

    private void openPanel(String loggedId, String expDisplay, String statusMsg) {
        if (controlPanel != null && controlPanel.isDisplayable()) {
            controlPanel.dispose();
        }
        controlPanel = new ControlPanelDialog(this, client, loggedId, expDisplay, v -> {
        });
        controlPanel.setVisible(true);
        status.setText("验证成功，主控制面板已在新窗口打开");
    }

    private void testNet() {
        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                boolean ok = client.connect();
                javax.swing.SwingUtilities.invokeLater(() ->
                        status.setText(ok ? "网络连接正常" : "网络连接异常"));
                return null;
            }
        }.execute();
    }

    private void checkVersion() {
        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                BSPHPAPIResult r = client.getVersion();
                String v = r.message();
                if (v == null || v.isEmpty()) v = "版本获取失败";
                else v = "当前版本：" + v;
                final String vf = v;
                javax.swing.SwingUtilities.invokeLater(() -> status.setText(vf));
                return null;
            }
        }.execute();
    }

    private void activate() {
        String icid = machineRenewInput.getText().trim();
        if (icid.isEmpty()) {
            status.setText("【机器码】请输入机器码（账号）");
            return;
        }
        String ka = mcCardPwd.getText().trim();
        if (ka.isEmpty()) {
            status.setText("请输入充值卡号");
            return;
        }
        String pwd = mcCardId.getText().trim();
        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                BSPHPAPIResult r = client.rechargeCard(icid, ka, pwd);
                String msg = r.message();
                if (msg == null || msg.isEmpty()) msg = "（无 data）";
                final String mf = msg;
                javax.swing.SwingUtilities.invokeLater(() ->
                        status.setText("[chong.ic] code=" + r.code + " " + mf));
                return null;
            }
        }.execute();
    }
}
