import { FolkShape } from "./folk-shape";
import { css, html } from "./tags";

const styles = css`
	:host {
		background: var(--rs-bg-surface, #fff);
		color: var(--rs-text-primary, #1e293b);
		border-radius: 8px;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
		min-width: 280px;
		min-height: 200px;
	}

	.header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 12px;
		background: #d97706;
		color: white;
		border-radius: 8px 8px 0 0;
		font-size: 12px;
		font-weight: 600;
		cursor: move;
	}

	.header-title {
		display: flex;
		align-items: center;
		gap: 6px;
	}

	.header-actions button {
		background: transparent;
		border: none;
		color: white;
		cursor: pointer;
		padding: 2px 6px;
		border-radius: 4px;
		font-size: 14px;
	}

	.header-actions button:hover {
		background: rgba(255, 255, 255, 0.2);
	}

	.budget-body {
		padding: 12px;
	}

	.budget-summary {
		margin-bottom: 12px;
	}

	.budget-row {
		display: flex;
		justify-content: space-between;
		font-size: 12px;
		margin-bottom: 4px;
	}

	.budget-row .label {
		color: var(--rs-text-muted, #64748b);
	}

	.budget-row .value {
		font-weight: 600;
		color: var(--rs-text-primary, #e2e8f0);
	}

	.budget-row .remaining {
		color: #059669;
	}

	.budget-row .over {
		color: #dc2626;
	}

	.progress-bar {
		width: 100%;
		height: 8px;
		background: var(--rs-bg-surface-raised, #334155);
		border-radius: 4px;
		overflow: hidden;
		margin: 8px 0 12px;
	}

	.progress-fill {
		height: 100%;
		border-radius: 4px;
		transition: width 0.3s ease;
	}

	.progress-fill.ok {
		background: #059669;
	}

	.progress-fill.warning {
		background: #d97706;
	}

	.progress-fill.danger {
		background: #dc2626;
	}

	.expense-list {
		max-height: 200px;
		overflow-y: auto;
	}

	.expense-item {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 6px 8px;
		font-size: 12px;
		border-radius: 4px;
		margin-bottom: 3px;
		background: var(--rs-bg-surface-sunken, #0f172a);
	}

	.expense-item:hover {
		background: var(--rs-bg-hover, rgba(255, 255, 255, 0.05));
	}

	.expense-desc {
		color: var(--rs-text-primary, #e2e8f0);
		font-weight: 500;
	}

	.expense-cat {
		font-size: 9px;
		color: var(--rs-text-muted, #64748b);
	}

	.expense-amount {
		font-weight: 600;
		color: #dc2626;
	}

	.add-form {
		display: flex;
		gap: 4px;
		padding: 8px 12px;
		border-top: 1px solid #e2e8f0;
	}

	.add-form input {
		flex: 1;
		padding: 6px 8px;
		border: 1px solid var(--rs-input-border, #e2e8f0);
		border-radius: 4px;
		font-size: 12px;
		outline: none;
		background: var(--rs-input-bg, #fff);
		color: var(--rs-input-text, inherit);
	}

	.add-form input:focus {
		border-color: #d97706;
	}

	.add-form input.amount-input {
		width: 80px;
		flex: 0;
	}

	.empty-state {
		text-align: center;
		padding: 16px;
		color: #94a3b8;
		font-size: 12px;
	}
`;

export interface BudgetExpense {
	id: string;
	description: string;
	amount: number;
	category: string;
	date?: string;
}

declare global {
	interface HTMLElementTagNameMap {
		"folk-budget": FolkBudget;
	}
}

export class FolkBudget extends FolkShape {
	static override tagName = "folk-budget";

	static {
		const sheet = new CSSStyleSheet();
		const parentRules = Array.from(FolkShape.styles.cssRules)
			.map((r) => r.cssText)
			.join("\n");
		const childRules = Array.from(styles.cssRules)
			.map((r) => r.cssText)
			.join("\n");
		sheet.replaceSync(`${parentRules}\n${childRules}`);
		this.styles = sheet;
	}

	#budgetTotal = 0;
	#currency = "USD";
	#expenses: BudgetExpense[] = [];
	#listEl: HTMLElement | null = null;
	#summaryEl: HTMLElement | null = null;
	#progressEl: HTMLElement | null = null;

	get budgetTotal() { return this.#budgetTotal; }
	set budgetTotal(v: number) {
		this.#budgetTotal = v;
		this.#render();
		this.dispatchEvent(new CustomEvent("content-change"));
	}

	get currency() { return this.#currency; }
	set currency(v: string) {
		this.#currency = v;
		this.#render();
	}

	get expenses() { return this.#expenses; }
	set expenses(v: BudgetExpense[]) {
		this.#expenses = v;
		this.#render();
		this.dispatchEvent(new CustomEvent("content-change"));
	}

	get spent() {
		return this.#expenses.reduce((sum, e) => sum + e.amount, 0);
	}

	addExpense(expense: BudgetExpense) {
		this.#expenses.push(expense);
		this.#render();
		this.dispatchEvent(new CustomEvent("content-change"));
	}

	override createRenderRoot() {
		const root = super.createRenderRoot();

		const wrapper = document.createElement("div");
		wrapper.innerHTML = html`
			<div class="header">
				<span class="header-title">
					<span>💰</span>
					<span>Budget</span>
				</span>
				<div class="header-actions">
					<button class="close-btn" title="Close">×</button>
				</div>
			</div>
			<div class="budget-body">
				<div class="budget-summary"></div>
				<div class="progress-bar"><div class="progress-fill"></div></div>
				<div class="expense-list"></div>
			</div>
			<div class="add-form">
				<input type="text" placeholder="Expense description..." class="desc-input" />
				<input type="number" placeholder="0.00" class="amount-input" step="0.01" />
			</div>
		`;

		const slot = root.querySelector("slot");
		const containerDiv = slot?.parentElement as HTMLElement;
		if (containerDiv) {
			containerDiv.replaceWith(wrapper);
		}

		this.#summaryEl = wrapper.querySelector(".budget-summary");
		this.#progressEl = wrapper.querySelector(".progress-fill");
		this.#listEl = wrapper.querySelector(".expense-list");

		const closeBtn = wrapper.querySelector(".close-btn") as HTMLButtonElement;
		const descInput = wrapper.querySelector(".desc-input") as HTMLInputElement;
		const amountInput = wrapper.querySelector(".amount-input") as HTMLInputElement;

		closeBtn.addEventListener("click", (e) => {
			e.stopPropagation();
			this.dispatchEvent(new CustomEvent("close"));
		});

		const addExpense = () => {
			if (descInput.value.trim() && amountInput.value) {
				this.addExpense({
					id: `exp-${Date.now()}`,
					description: descInput.value.trim(),
					amount: Number(amountInput.value),
					category: "OTHER",
				});
				descInput.value = "";
				amountInput.value = "";
			}
		};

		descInput.addEventListener("keydown", (e) => {
			if (e.key === "Enter") { e.stopPropagation(); addExpense(); }
		});
		amountInput.addEventListener("keydown", (e) => {
			if (e.key === "Enter") { e.stopPropagation(); addExpense(); }
		});
		descInput.addEventListener("click", (e) => e.stopPropagation());
		amountInput.addEventListener("click", (e) => e.stopPropagation());

		this.#render();
		return root;
	}

	#escapeHtml(text: string): string {
		const div = document.createElement("div");
		div.textContent = text;
		return div.innerHTML;
	}

	#render() {
		if (!this.#summaryEl || !this.#progressEl || !this.#listEl) return;

		const spent = this.spent;
		const remaining = this.#budgetTotal - spent;
		const pct = this.#budgetTotal > 0 ? (spent / this.#budgetTotal) * 100 : 0;

		this.#summaryEl.innerHTML = `
			<div class="budget-row">
				<span class="label">Budget</span>
				<span class="value">${this.#currency} ${this.#budgetTotal.toLocaleString()}</span>
			</div>
			<div class="budget-row">
				<span class="label">Spent</span>
				<span class="value">${this.#currency} ${spent.toLocaleString()}</span>
			</div>
			<div class="budget-row">
				<span class="label">Remaining</span>
				<span class="value ${remaining >= 0 ? 'remaining' : 'over'}">${this.#currency} ${Math.abs(remaining).toLocaleString()}${remaining < 0 ? ' over' : ''}</span>
			</div>
		`;

		this.#progressEl.style.width = `${Math.min(pct, 100)}%`;
		this.#progressEl.className = `progress-fill ${pct > 90 ? 'danger' : pct > 70 ? 'warning' : 'ok'}`;

		if (this.#expenses.length === 0) {
			this.#listEl.innerHTML = '<div class="empty-state">No expenses yet</div>';
		} else {
			this.#listEl.innerHTML = this.#expenses
				.slice()
				.reverse()
				.map((e) => `
					<div class="expense-item">
						<div>
							<div class="expense-desc">${this.#escapeHtml(e.description)}</div>
							<div class="expense-cat">${this.#escapeHtml(e.category)}</div>
						</div>
						<span class="expense-amount">-${this.#currency} ${e.amount.toLocaleString()}</span>
					</div>
				`)
				.join("");
		}
	}

	static override fromData(data: Record<string, any>): FolkBudget {
		const shape = FolkShape.fromData(data) as FolkBudget;
		if (data.budgetTotal != null) shape.budgetTotal = data.budgetTotal;
		if (data.currency !== undefined) shape.currency = data.currency;
		if (Array.isArray(data.expenses)) shape.expenses = data.expenses;
		return shape;
	}

	override applyData(data: Record<string, any>): void {
		super.applyData(data);
		if (data.budgetTotal != null && data.budgetTotal !== this.budgetTotal) this.budgetTotal = data.budgetTotal;
		if (data.currency !== undefined && data.currency !== this.currency) this.currency = data.currency;
		if (Array.isArray(data.expenses) && JSON.stringify(data.expenses) !== JSON.stringify(this.expenses)) this.expenses = data.expenses;
	}

	override toJSON() {
		return {
			...super.toJSON(),
			type: "folk-budget",
			budgetTotal: this.#budgetTotal,
			currency: this.#currency,
			expenses: this.#expenses,
		};
	}
}
