/**
 * <folk-crm-view> — API-driven CRM interface.
 *
 * Tabbed view: Pipeline | Contacts | Companies | Graph
 * Fetches from per-space API endpoints on the rNetwork module.
 */

interface Opportunity {
	id: string;
	name: string;
	stage: string;
	amount?: { amountMicros: number; currencyCode: string };
	company?: { id: string; name: string };
	pointOfContact?: { id: string; name: { firstName: string; lastName: string } };
	createdAt?: string;
	closeDate?: string;
}

interface Person {
	id: string;
	name: { firstName: string; lastName: string };
	email?: { primaryEmail: string };
	phone?: { primaryPhoneNumber: string };
	city?: string;
	company?: { id: string; name: { firstName: string; lastName: string } };
	createdAt?: string;
}

interface Company {
	id: string;
	name: string;
	domainName?: { primaryLinkUrl: string };
	employees?: number;
	address?: { addressCity: string; addressCountry: string };
	createdAt?: string;
}

type Tab = "pipeline" | "contacts" | "companies" | "graph";

const PIPELINE_STAGES = [
	"INCOMING",
	"MEETING",
	"PROPOSAL",
	"CLOSED_WON",
	"CLOSED_LOST",
];

const STAGE_LABELS: Record<string, string> = {
	INCOMING: "Incoming",
	MEETING: "Meeting",
	PROPOSAL: "Proposal",
	CLOSED_WON: "Won",
	CLOSED_LOST: "Lost",
};

class FolkCrmView extends HTMLElement {
	private shadow: ShadowRoot;
	private space = "";
	private activeTab: Tab = "pipeline";
	private searchQuery = "";
	private sortColumn = "";
	private sortAsc = true;

	private opportunities: Opportunity[] = [];
	private people: Person[] = [];
	private companies: Company[] = [];
	private loading = true;
	private error = "";

	constructor() {
		super();
		this.shadow = this.attachShadow({ mode: "open" });
	}

	connectedCallback() {
		this.space = this.getAttribute("space") || "demo";
		this.render();
		this.loadData();
	}

	private getApiBase(): string {
		const path = window.location.pathname;
		const match = path.match(/^(\/[^/]+)?\/rnetwork/);
		return match ? match[0] : "";
	}

	private async loadData() {
		const base = this.getApiBase();
		try {
			const [oppRes, peopleRes, compRes] = await Promise.all([
				fetch(`${base}/api/opportunities`),
				fetch(`${base}/api/people`),
				fetch(`${base}/api/companies`),
			]);
			if (oppRes.ok) {
				const d = await oppRes.json();
				this.opportunities = d.opportunities || [];
			}
			if (peopleRes.ok) {
				const d = await peopleRes.json();
				this.people = d.people || [];
			}
			if (compRes.ok) {
				const d = await compRes.json();
				this.companies = d.companies || [];
			}
		} catch (e) {
			this.error = "Failed to load CRM data";
		}
		this.loading = false;
		this.render();
	}

	private formatAmount(amount?: { amountMicros: number; currencyCode: string }): string {
		if (!amount || !amount.amountMicros) return "-";
		const value = amount.amountMicros / 1_000_000;
		const currency = amount.currencyCode || "USD";
		try {
			return new Intl.NumberFormat("en-US", { style: "currency", currency, maximumFractionDigits: 0 }).format(value);
		} catch {
			return `${currency} ${value.toLocaleString()}`;
		}
	}

	private personName(p?: { firstName: string; lastName: string }): string {
		if (!p) return "-";
		return [p.firstName, p.lastName].filter(Boolean).join(" ") || "-";
	}

	private companyName(c?: { id: string; name: string | { firstName: string; lastName: string } }): string {
		if (!c) return "-";
		if (typeof c.name === "string") return c.name;
		return [c.name?.firstName, c.name?.lastName].filter(Boolean).join(" ") || "-";
	}

	private formatDate(d?: string): string {
		if (!d) return "-";
		try { return new Date(d).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }); }
		catch { return "-"; }
	}

	// ── Pipeline view ──
	private renderPipeline(): string {
		if (this.opportunities.length === 0) {
			return `<div class="empty-state">No opportunities found${this.space === "demo" ? " — connect a Twenty workspace to see pipeline data" : ""}.</div>`;
		}

		const byStage = new Map<string, Opportunity[]>();
		for (const stage of PIPELINE_STAGES) byStage.set(stage, []);
		for (const opp of this.opportunities) {
			const stage = opp.stage || "INCOMING";
			const list = byStage.get(stage) || byStage.get("INCOMING")!;
			list.push(opp);
		}

		return `<div class="pipeline-grid">
			${PIPELINE_STAGES.map(stage => {
				const opps = byStage.get(stage) || [];
				const total = opps.reduce((s, o) => s + (o.amount?.amountMicros || 0), 0) / 1_000_000;
				const stageClass = stage.toLowerCase().replace(/_/g, "-");
				return `<div class="pipeline-column">
					<div class="pipeline-header stage-${stageClass}">
						<span class="pipeline-stage-name">${STAGE_LABELS[stage] || stage}</span>
						<span class="pipeline-count">${opps.length}</span>
					</div>
					${total > 0 ? `<div class="pipeline-total">${this.formatAmount({ amountMicros: total * 1_000_000, currencyCode: "USD" })}</div>` : ""}
					<div class="pipeline-cards">
						${opps.map(opp => `<div class="pipeline-card">
							<div class="card-name">${this.esc(opp.name)}</div>
							<div class="card-amount">${this.formatAmount(opp.amount)}</div>
							${opp.company?.name ? `<div class="card-company">${this.esc(opp.company.name)}</div>` : ""}
							${opp.pointOfContact ? `<div class="card-contact">${this.esc(this.personName(opp.pointOfContact.name))}</div>` : ""}
							${opp.closeDate ? `<div class="card-date">Close: ${this.formatDate(opp.closeDate)}</div>` : ""}
						</div>`).join("")}
					</div>
				</div>`;
			}).join("")}
		</div>`;
	}

	// ── Contacts table ──
	private renderContacts(): string {
		let filtered = this.people;
		if (this.searchQuery.trim()) {
			const q = this.searchQuery.toLowerCase();
			filtered = filtered.filter(p =>
				this.personName(p.name).toLowerCase().includes(q) ||
				(p.email?.primaryEmail || "").toLowerCase().includes(q) ||
				this.companyName(p.company).toLowerCase().includes(q) ||
				(p.city || "").toLowerCase().includes(q)
			);
		}

		if (this.sortColumn) {
			filtered = [...filtered].sort((a, b) => {
				let va = "", vb = "";
				switch (this.sortColumn) {
					case "name": va = this.personName(a.name); vb = this.personName(b.name); break;
					case "email": va = a.email?.primaryEmail || ""; vb = b.email?.primaryEmail || ""; break;
					case "company": va = this.companyName(a.company); vb = this.companyName(b.company); break;
					case "city": va = a.city || ""; vb = b.city || ""; break;
				}
				const cmp = va.localeCompare(vb);
				return this.sortAsc ? cmp : -cmp;
			});
		}

		if (filtered.length === 0) {
			return `<div class="empty-state">${this.searchQuery ? "No contacts match your search." : "No contacts found."}</div>`;
		}

		const sortIcon = (col: string) => this.sortColumn === col ? (this.sortAsc ? " \u25B2" : " \u25BC") : "";

		return `<table class="data-table">
			<thead><tr>
				<th data-sort="name">Name${sortIcon("name")}</th>
				<th data-sort="email">Email${sortIcon("email")}</th>
				<th data-sort="company">Company${sortIcon("company")}</th>
				<th data-sort="city">City${sortIcon("city")}</th>
				<th>Phone</th>
			</tr></thead>
			<tbody>
				${filtered.map(p => `<tr>
					<td class="cell-name">${this.esc(this.personName(p.name))}</td>
					<td class="cell-email">${p.email?.primaryEmail ? this.esc(p.email.primaryEmail) : "-"}</td>
					<td>${this.esc(this.companyName(p.company))}</td>
					<td>${this.esc(p.city || "-")}</td>
					<td>${this.esc(p.phone?.primaryPhoneNumber || "-")}</td>
				</tr>`).join("")}
			</tbody>
		</table>
		<div class="table-footer">${filtered.length} contact${filtered.length !== 1 ? "s" : ""}</div>`;
	}

	// ── Companies table ──
	private renderCompanies(): string {
		let filtered = this.companies;
		if (this.searchQuery.trim()) {
			const q = this.searchQuery.toLowerCase();
			filtered = filtered.filter(c =>
				(c.name || "").toLowerCase().includes(q) ||
				(c.domainName?.primaryLinkUrl || "").toLowerCase().includes(q) ||
				(c.address?.addressCity || "").toLowerCase().includes(q)
			);
		}

		if (this.sortColumn) {
			filtered = [...filtered].sort((a, b) => {
				let va = "", vb = "";
				switch (this.sortColumn) {
					case "name": va = a.name || ""; vb = b.name || ""; break;
					case "domain": va = a.domainName?.primaryLinkUrl || ""; vb = b.domainName?.primaryLinkUrl || ""; break;
					case "city": va = a.address?.addressCity || ""; vb = b.address?.addressCity || ""; break;
					case "employees": return this.sortAsc ? (a.employees || 0) - (b.employees || 0) : (b.employees || 0) - (a.employees || 0);
				}
				const cmp = va.localeCompare(vb);
				return this.sortAsc ? cmp : -cmp;
			});
		}

		if (filtered.length === 0) {
			return `<div class="empty-state">${this.searchQuery ? "No companies match your search." : "No companies found."}</div>`;
		}

		const sortIcon = (col: string) => this.sortColumn === col ? (this.sortAsc ? " \u25B2" : " \u25BC") : "";

		return `<table class="data-table">
			<thead><tr>
				<th data-sort="name">Name${sortIcon("name")}</th>
				<th data-sort="domain">Domain${sortIcon("domain")}</th>
				<th data-sort="employees">Employees${sortIcon("employees")}</th>
				<th data-sort="city">City${sortIcon("city")}</th>
				<th>Country</th>
			</tr></thead>
			<tbody>
				${filtered.map(c => `<tr>
					<td class="cell-name">${this.esc(c.name || "-")}</td>
					<td class="cell-domain">${c.domainName?.primaryLinkUrl ? `<a href="${this.esc(c.domainName.primaryLinkUrl)}" target="_blank" rel="noopener">${this.esc(c.domainName.primaryLinkUrl)}</a>` : "-"}</td>
					<td>${c.employees ?? "-"}</td>
					<td>${this.esc(c.address?.addressCity || "-")}</td>
					<td>${this.esc(c.address?.addressCountry || "-")}</td>
				</tr>`).join("")}
			</tbody>
		</table>
		<div class="table-footer">${filtered.length} compan${filtered.length !== 1 ? "ies" : "y"}</div>`;
	}

	// ── Graph link ──
	private renderGraphTab(): string {
		const base = this.getApiBase().replace(/\/crm$/, "");
		return `<div class="graph-link-section">
			<p>View the interactive force-directed relationship graph for this space.</p>
			<a href="${base || `/${this.space}/rnetwork`}" class="graph-link-btn">Open Network Graph</a>
		</div>`;
	}

	// ── Main render ──
	private render() {
		const tabs: { id: Tab; label: string; count: number }[] = [
			{ id: "pipeline", label: "Pipeline", count: this.opportunities.length },
			{ id: "contacts", label: "Contacts", count: this.people.length },
			{ id: "companies", label: "Companies", count: this.companies.length },
			{ id: "graph", label: "Graph", count: 0 },
		];

		let content = "";
		if (this.loading) {
			content = `<div class="loading">Loading CRM data...</div>`;
		} else if (this.error) {
			content = `<div class="error">${this.esc(this.error)}</div>`;
		} else {
			switch (this.activeTab) {
				case "pipeline": content = this.renderPipeline(); break;
				case "contacts": content = this.renderContacts(); break;
				case "companies": content = this.renderCompanies(); break;
				case "graph": content = this.renderGraphTab(); break;
			}
		}

		const showSearch = this.activeTab === "contacts" || this.activeTab === "companies";

		this.shadow.innerHTML = `
		<style>
			:host { display: block; font-family: system-ui, -apple-system, sans-serif; color: var(--rs-text-primary); }
			* { box-sizing: border-box; }

			.crm-header { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
			.crm-title { font-size: 15px; font-weight: 600; color: var(--rs-text-primary); }

			.tabs { display: flex; gap: 2px; background: var(--rs-input-bg); border-radius: 10px; padding: 3px; margin-bottom: 16px; }
			.tab {
				padding: 8px 16px; border-radius: 8px; border: none;
				background: transparent; color: var(--rs-text-muted); cursor: pointer; font-size: 13px;
				font-weight: 500; transition: all 0.15s;
			}
			.tab:hover { color: var(--rs-text-secondary); }
			.tab.active { background: var(--rs-bg-surface); color: var(--rs-text-primary); }
			.tab-count { font-size: 11px; color: var(--rs-text-muted); margin-left: 4px; }
			.tab.active .tab-count { color: var(--rs-primary-hover); }

			.toolbar { display: flex; gap: 8px; margin-bottom: 16px; align-items: center; }
			.search-input {
				border: 1px solid var(--rs-input-border); border-radius: 8px; padding: 8px 12px;
				background: var(--rs-input-bg); color: var(--rs-input-text); font-size: 13px; width: 260px; outline: none;
			}
			.search-input:focus { border-color: var(--rs-primary-hover); }

			.loading { text-align: center; color: var(--rs-text-muted); padding: 60px 20px; font-size: 14px; }
			.error { text-align: center; color: var(--rs-error); padding: 40px 20px; }
			.empty-state { text-align: center; color: var(--rs-text-muted); padding: 60px 20px; font-size: 14px; }

			/* ── Pipeline grid ── */
			.pipeline-grid {
				display: grid;
				grid-template-columns: repeat(${PIPELINE_STAGES.length}, 1fr);
				gap: 12px;
				overflow-x: auto;
			}
			.pipeline-column { min-width: 180px; }
			.pipeline-header {
				padding: 8px 12px; border-radius: 8px 8px 0 0;
				display: flex; align-items: center; justify-content: space-between;
				font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
			}
			.stage-incoming { background: rgba(59, 130, 246, 0.15); color: #3b82f6; }
			.stage-meeting { background: rgba(34, 197, 94, 0.15); color: #22c55e; }
			.stage-proposal { background: rgba(245, 158, 11, 0.15); color: #f59e0b; }
			.stage-closed-won { background: rgba(34, 197, 94, 0.2); color: #16a34a; }
			.stage-closed-lost { background: rgba(239, 68, 68, 0.15); color: #ef4444; }
			.pipeline-count {
				background: rgba(255,255,255,0.1); padding: 1px 7px; border-radius: 10px;
				font-size: 11px;
			}
			.pipeline-total { font-size: 12px; color: var(--rs-text-muted); padding: 4px 12px; }
			.pipeline-cards { display: flex; flex-direction: column; gap: 8px; padding-top: 8px; }
			.pipeline-card {
				background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px;
				padding: 12px; transition: border-color 0.15s;
			}
			.pipeline-card:hover { border-color: var(--rs-border-strong); }
			.card-name { font-size: 13px; font-weight: 600; color: var(--rs-text-primary); margin-bottom: 4px; }
			.card-amount { font-size: 14px; font-weight: 700; color: var(--rs-primary-hover); margin-bottom: 6px; }
			.card-company { font-size: 12px; color: var(--rs-text-secondary); }
			.card-contact { font-size: 11px; color: var(--rs-text-muted); margin-top: 2px; }
			.card-date { font-size: 11px; color: var(--rs-text-muted); margin-top: 4px; }

			/* ── Data tables ── */
			.data-table {
				width: 100%; border-collapse: collapse;
				background: var(--rs-input-bg); border-radius: 10px; overflow: hidden;
			}
			.data-table th {
				text-align: left; padding: 10px 14px; font-size: 11px; font-weight: 600;
				color: var(--rs-text-muted); text-transform: uppercase; letter-spacing: 0.04em;
				border-bottom: 1px solid var(--rs-border); cursor: pointer; user-select: none;
				white-space: nowrap;
			}
			.data-table th:hover { color: var(--rs-text-secondary); }
			.data-table td {
				padding: 10px 14px; font-size: 13px; border-bottom: 1px solid var(--rs-border-subtle);
				color: var(--rs-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
				max-width: 250px;
			}
			.data-table tr:hover td { background: var(--rs-bg-hover); }
			.cell-name { font-weight: 500; color: var(--rs-text-primary); }
			.cell-email { color: #93c5fd; }
			.cell-domain a { color: #93c5fd; text-decoration: none; }
			.cell-domain a:hover { text-decoration: underline; }
			.table-footer { font-size: 12px; color: var(--rs-text-muted); padding: 10px 14px; }

			/* ── Graph tab ── */
			.graph-link-section { text-align: center; padding: 60px 20px; }
			.graph-link-section p { color: var(--rs-text-muted); font-size: 14px; margin-bottom: 16px; }
			.graph-link-btn {
				display: inline-block; padding: 10px 24px; border-radius: 8px;
				background: var(--rs-primary-hover); color: #fff; text-decoration: none;
				font-size: 14px; font-weight: 500; transition: background 0.15s;
			}
			.graph-link-btn:hover { background: var(--rs-primary); }

			@media (max-width: 900px) {
				.pipeline-grid { grid-template-columns: repeat(2, 1fr); }
			}
			@media (max-width: 600px) {
				.pipeline-grid { grid-template-columns: 1fr; }
				.tabs { flex-wrap: wrap; }
				.toolbar { flex-direction: column; align-items: stretch; }
				.search-input { width: 100%; }
				.data-table td, .data-table th { padding: 8px 10px; font-size: 12px; }
			}
		</style>

		<div class="crm-header">
			<span class="crm-title">CRM</span>
		</div>

		<div class="tabs">
			${tabs.map(t => `<button class="tab ${this.activeTab === t.id ? "active" : ""}" data-tab="${t.id}">
				${t.label}${t.count > 0 ? `<span class="tab-count">${t.count}</span>` : ""}
			</button>`).join("")}
		</div>

		${showSearch ? `<div class="toolbar">
			<input class="search-input" type="text" placeholder="Search..." id="crm-search" value="${this.esc(this.searchQuery)}">
		</div>` : ""}

		<div class="crm-content">${content}</div>
		`;

		this.attachListeners();
	}

	private attachListeners() {
		// Tab switching
		this.shadow.querySelectorAll("[data-tab]").forEach(el => {
			el.addEventListener("click", () => {
				this.activeTab = (el as HTMLElement).dataset.tab as Tab;
				this.searchQuery = "";
				this.sortColumn = "";
				this.sortAsc = true;
				this.render();
			});
		});

		// Search
		let searchTimeout: any;
		this.shadow.getElementById("crm-search")?.addEventListener("input", (e) => {
			this.searchQuery = (e.target as HTMLInputElement).value;
			clearTimeout(searchTimeout);
			searchTimeout = setTimeout(() => this.render(), 200);
		});

		// Sort columns
		this.shadow.querySelectorAll("[data-sort]").forEach(el => {
			el.addEventListener("click", () => {
				const col = (el as HTMLElement).dataset.sort!;
				if (this.sortColumn === col) {
					this.sortAsc = !this.sortAsc;
				} else {
					this.sortColumn = col;
					this.sortAsc = true;
				}
				this.render();
			});
		});
	}

	private esc(s: string): string {
		const d = document.createElement("div");
		d.textContent = s || "";
		return d.innerHTML;
	}
}

customElements.define("folk-crm-view", FolkCrmView);
