import MainControl from "@/Common/MainControl/MainControl";
import CSMessage from "@/Common/Message/CSMessage";
import { GameItemsContext, gameObj } from "@/context/GameItemsContext";
import { SDAccountLoginRequest } from "@/define/Request/AccountRequest";
import { SlotInRequest } from "@/define/Request/SlotRequest";
import { CoroutineV2 } from "@/Engine/CatanEngine/CoroutineV2/CoroutineV2";
import { INetResponse } from "@/Engine/CatanEngine/NetManagerV2/Core/INetResponse";
import { NetConnector } from "@/Engine/CatanEngine/NetManagerV2/NetConnector";
import { NetManagerSD } from "@/Engine/CatanEngine/NetManagerV2/NetManagerSD";
import CSSettingsSDV3 from "@/FormTableSD/CSSettingsSDV3";
import { SlotsetTableRow } from "@/FormTableSD/Tables/SlotsetTable";
import GameManager from "@/modules/GameManager";
import {
	Button,
	Card,
	Checkbox,
	Divider,
	Dropdown,
	Input,
	Space,
} from "antd";
import dayjs from "dayjs";
import { ChangeEvent, useContext, useEffect, useState } from "react";
import A from "../CustomA";

const SDGame = (props: ISDGame) => {
	const { gameUrl, onClickSlotOut } = props;
	const { gameData } = useContext(GameItemsContext);
	const { nowSlotId } = gameData;

	const [, setRender] = useState(0);
	const [isOK, setIsOK] = useState<boolean>(false);
	const [isSpin, setIsSpin] = useState<boolean>(false);
	const [items, setItems] = useState<any[]>([]);
	const [bet, setBet] = useState<number>(0);
	const [delay, setDelay] = useState<number>(0.1);
	const [isRatioStop, setIsRatioStop] = useState<boolean>(false);
	const [ratioStop, setRatioStop] = useState<number>(200);
	const [isCountStop, setIsCountStop] = useState<boolean>(false);
	const [countStop, setCountStop] = useState<number>(200);
	const [log, setLog] = useState<string[]>([]);

	let conn: NetConnector = undefined;

	/* ------------------- 原本的 onLoad 流程不動 ------------------- */
	function* onLoad(): IterableIterator<any> {
		reset();
		const url = new URL(gameUrl);
		const token = url.searchParams.get("token");
		const slotid = +url.searchParams.get("slotid");
		const host = url.searchParams.get("host");
		const port = 9005;

		GameManager.SlotData.SlotId = slotid;
		GameManager.SlotData.IsRatioStop = isRatioStop;
		GameManager.SlotData.RatioStop = ratioStop;
		GameManager.SlotData.IsCountStop = isCountStop;
		GameManager.SlotData.CountStop = countStop;

		conn = new NetConnector("https://" + host, port);
		conn.OnDataReceived.AddCallback(onNetDataReceived);
		conn.OnDisconnected.AddCallback(onNetDisconnected);

		loadJSON(slotid);
		setSlotClass();

		NetManagerSD.Initialize(conn);
		yield NetManagerSD.ConnectAsync();
		yield* login(token);
		yield* slotIn();
	}

	function onClose() {
		CoroutineV2.StopCoroutinesBy("Spin");
		reset();
	}

	function reset() {
		GameManager.SlotData.SlotId = undefined;
		GameManager.SlotData.SlotClass = undefined;
		GameManager.SlotData.IsSpin = undefined;
		GameManager.SlotData.NowBet = undefined;
		GameManager.SlotData.IsRatioStop = undefined;
		GameManager.SlotData.RatioStop = undefined;
		GameManager.SlotData.IsCountStop = undefined;
		GameManager.SlotData.CountStop = undefined;
	}

	/* ------------------- 原本流程全部保留 ------------------- */
	function* login(token: string): IterableIterator<any> {
		const req = new SDAccountLoginRequest(token);
		yield req.SendAsync(true);
		const resp = req.Result;
		if (!resp.IsValid) {
			CSMessage.NetError(resp.Method, resp.Status, "SD Account Login Fail");
			return;
		}
	}

	function* slotIn(): IterableIterator<any> {
		let req = new SlotInRequest(GameManager.SlotData.SlotId);
		yield req.SendAsync(true);
		let resp = req.Result;

		if (resp.IsValid) {
			const br: number[] = resp.Data["br"];
			const db: number = resp.Data["db"];

			setItems(
				br.map((b: number, i: number) => ({
					key: i,
					label: (
						<A href="#" onClick={() => { setBet(b); GameManager.SlotData.NowBet = b; }}>
							{b}
						</A>
					),
				}))
			);

			setBet(br[db]);
			GameManager.SlotData.NowBet = br[db];
			setIsOK(true);
		}
	}

	async function loadJSON(slotid: number) {
		let slotset: SlotsetTableRow = CSSettingsSDV3.Slotset[slotid];
		for (let name of slotset.FormName) {
			await MainControl.DownloadFormSetting(name);
		}
	}

	async function setSlotClass() {
		let slotGroup = await import(`../../define/Game/Base/Slot`);
		let slot = slotGroup[`Slot${GameManager.SlotData.SlotId}`] || slotGroup.SlotBase;
		GameManager.SlotData.SlotClass = new slot(GameManager.SlotData.SlotId, AddLog);
	}

	/* ------------------- Spin, Stop 等邏輯不動 ------------------- */
	async function OnClickSpin() {
		GameManager.SlotData.IsSpin = true;
		setIsSpin(true);
		CoroutineV2.Single(spin()).Start("Spin");
	}

	function OnClickStop() {
		GameManager.SlotData.IsSpin = false;
		setIsSpin(false);
	}

	function* spin(): IterableIterator<any> {
		const { player } = gameObj;
		if (player.m < GameManager.SlotData.NowBet) {
			noMoney();
			OnClickStop();
			return;
		}

		if (isCountStop) {
			if (GameManager.SlotData.CountStop <= 0) {
				OnClickStop();
				return;
			}
			GameManager.SlotData.CountStop--;
			setCountStop((v) => v - 1);
		}

		yield* GameManager.SlotData.SlotClass.Spin(bet, OnClickStop);
		yield CoroutineV2.WaitTime(delay);

		if (GameManager.SlotData.IsSpin) {
			yield* spin();
		} else {
			setIsSpin(false);
		}
	}

	function noMoney() {
		const { player } = gameObj;
		AddLog(`金額不足：${player.m}`);
	}

	function AddLog(s: string) {
		const time = dayjs().format("YYYY/MM/DD HH:mm:ss");
		setLog((v) => {
			if (v.length > 200) v.pop();
			return [`${time}  ${s}`, ...v];
		});
		setRender((v) => v + 1);
	}

	/* ------------------- socket callbacks ------------------- */
	function onNetDataReceived(resp: INetResponse<any>) { }
	function onNetDisconnected() { conn?.OnDataReceived.RemoveAllCallbacks(); }

	useEffect(() => {
		CoroutineV2.Single(onLoad()).Start();
		return onClose;
	}, []);

	/* ------------------- UI：僅改善畫面，不改邏輯 ------------------- */
	return (
		<div style={rootStyle}>

			{/* 控制區 */}
			<Card title="🎮 機台控制" style={panelCardStyle}>

				{isOK && (
					<Space orientation="vertical" size="large" style={{ width: "100%" }}>

						{/* 押注 */}
						<div>
							<label style={labelStyle}>押注：</label>
							<Dropdown menu={{ items }} trigger={["click"]}>
								<Button>{bet}</Button>
							</Dropdown>
						</div>

						{/* 延遲 */}
						<div>
							<label style={labelStyle}>延遲：</label>
							<Input
								value={delay}
								onChange={(e: ChangeEvent<HTMLInputElement>) => setDelay(+e.target.value)}
								style={{ width: 100 }}
							/>
							<span>秒</span>
						</div>

						{/* 倍率停止 */}
						<div>
							<Checkbox
								checked={isRatioStop}
								onChange={(e) => { setIsRatioStop(e.target.checked); GameManager.SlotData.IsRatioStop = e.target.checked; }}
							>
								倍率停止
							</Checkbox>
							{isRatioStop && (
								<Input
									value={ratioStop}
									onChange={(e) => { setRatioStop(+e.target.value); GameManager.SlotData.RatioStop = +e.target.value; }}
									style={{ width: 100, marginLeft: 12 }}
								/>
							)}
						</div>

						{/* 次數停止 */}
						<div>
							<Checkbox
								checked={isCountStop}
								onChange={(e) => { setIsCountStop(e.target.checked); GameManager.SlotData.IsCountStop = e.target.checked; }}
							>
								次數停止
							</Checkbox>
							{isCountStop && (
								<Input
									value={countStop}
									onChange={(e) => { setCountStop(+e.target.value); GameManager.SlotData.CountStop = +e.target.value; }}
									style={{ width: 100, marginLeft: 12 }}
								/>
							)}
						</div>

						{/* Spin / Stop */}
						<div>
							{isSpin ? (
								<Button type="primary" danger onClick={OnClickStop} block>
									停止
								</Button>
							) : (
								<Button type="primary" onClick={OnClickSpin} block>
									開始旋轉
								</Button>
							)}
						</div>
					</Space>
				)}

				<Divider />

				<Button danger onClick={onClickSlotOut} block>
					離開機台
				</Button>
			</Card>

			{/* 日誌區 */}
			<Card title="📜 Log 日誌" style={logCardStyle}>
				<div style={logListStyle}>
					{log.map((text, i) => (
						<p key={i} style={{ margin: "4px 0" }}>
							{text}
						</p>
					))}
				</div>
			</Card>
		</div>
	);
};

export default SDGame;

/* ------------------- UI Style ------------------- */
const rootStyle: React.CSSProperties = {
	display: "flex",
	gap: "16px",
	height: "100vh",
	padding: "16px",
	boxSizing: "border-box",
};

const panelCardStyle: React.CSSProperties = {
	width: "30%",
	height: "100%",
	overflowY: "auto",
};

const logCardStyle: React.CSSProperties = {
	flex: 1,
	height: "100%",
	overflow: "hidden",
};

const logListStyle: React.CSSProperties = {
	height: "100%",
	overflowY: "scroll",
	paddingRight: 8,
};

const labelStyle: React.CSSProperties = {
	marginRight: 8,
	fontWeight: 600,
};

interface ISDGame {
	gameUrl: string;
	onClickSlotOut: () => void;
}
