import type { FC } from 'hono/jsx';
import { Layout } from './layout';
import type { Job, Node, MediaItem } from '../types';

interface ExecutePageProps {
	jobs: Array<{
		job: Job;
		item: MediaItem | null;
		node: Node | null;
	}>;
	nodes: Node[];
}

export const ExecutePage: FC<ExecutePageProps> = ({ jobs, nodes }) => {
	const pending = jobs.filter((j) => j.job.status === 'pending').length;
	const running = jobs.filter((j) => j.job.status === 'running').length;
	const done    = jobs.filter((j) => j.job.status === 'done').length;
	const errors  = jobs.filter((j) => j.job.status === 'error').length;

	const hasActiveJobs = running > 0;

	return (
		<Layout title="Execute" activeNav="execute">
			<div class="page-header">
				<h1>Execute Jobs</h1>
			</div>

			{/* Stats row */}
			<div class="flex-row" style="gap:0.75rem;margin-bottom:1.5rem;flex-wrap:wrap;">
				<span class="badge badge-pending">{pending} pending</span>
				{running > 0 && <span class="badge badge-running">{running} running</span>}
				{done > 0    && <span class="badge badge-done">{done} done</span>}
				{errors > 0  && <span class="badge badge-error">{errors} error(s)</span>}
			</div>

			{/* Controls */}
			<div class="flex-row" style="margin-bottom:1.5rem;gap:0.75rem;">
				{pending > 0 && (
					<form method="post" action="/execute/start" style="display:inline">
						<button type="submit">▶ Run all pending</button>
					</form>
				)}
				{jobs.length === 0 && (
					<p class="muted">No jobs yet. Go to <a href="/review">Review</a> and approve items first.</p>
				)}
			</div>

			{/* Job table */}
			{jobs.length > 0 && (
				<table class="data-table">
					<thead>
						<tr>
							<th>#</th>
							<th>Item</th>
							<th>Command</th>
							<th>Node</th>
							<th>Status</th>
							<th>Actions</th>
						</tr>
					</thead>
					<tbody>
						{jobs.map(({ job, item, node }) => (
							<JobRow key={job.id} job={job} item={item} node={node} nodes={nodes} />
						))}
					</tbody>
				</table>
			)}

			{/* SSE for live updates */}
			{hasActiveJobs && (
				<script
					dangerouslySetInnerHTML={{
						__html: `
(function() {
  var es = new EventSource('/execute/events');
  es.addEventListener('job_update', function(e) {
    var d = JSON.parse(e.data);
    var row = document.getElementById('job-row-' + d.id);
    if (!row) return;
    var statusCell = row.querySelector('.job-status');
    if (statusCell) statusCell.innerHTML = '<span class="badge badge-' + d.status + '">' + d.status + '</span>';
    var logCell = document.getElementById('job-log-' + d.id);
    if (logCell && d.output) logCell.textContent = d.output;
  });
  es.addEventListener('complete', function() { es.close(); location.reload(); });
})();
`,
					}}
				/>
			)}
		</Layout>
	);
};

const JobRow: FC<{ job: Job; item: MediaItem | null; node: Node | null; nodes: Node[] }> = ({
	job,
	item,
	node,
	nodes,
}) => {
	const itemName = item
		? (item.type === 'Episode' && item.series_name
			? `${item.series_name} S${String(item.season_number ?? 0).padStart(2, '0')}E${String(item.episode_number ?? 0).padStart(2, '0')}`
			: item.name)
		: `Item #${job.item_id}`;

	const cmdShort = job.command.length > 80 ? job.command.slice(0, 77) + '…' : job.command;

	return (
		<>
			<tr id={`job-row-${job.id}`}>
				<td class="mono">{job.id}</td>
				<td>
					<div class="truncate" style="max-width:200px;" title={itemName}>{itemName}</div>
					{item?.file_path && (
						<div class="mono muted truncate" style="font-size:0.72rem;max-width:200px;" title={item.file_path}>
							{item.file_path.split('/').pop()}
						</div>
					)}
				</td>
				<td class="mono" style="font-size:0.75rem;max-width:300px;">
					<span title={job.command}>{cmdShort}</span>
				</td>
				<td>
					{job.status === 'pending' ? (
						<form
							hx-post={`/execute/job/${job.id}/assign`}
							hx-target={`#job-row-${job.id}`}
							hx-swap="outerHTML"
							style="display:inline"
						>
							<select name="node_id" style="font-size:0.8rem;padding:0.2em 0.4em;" onchange="this.form.submit()">
								<option value="">Local</option>
								{nodes.map((n) => (
									<option key={n.id} value={n.id} selected={node?.id === n.id}>
										{n.name} ({n.host})
									</option>
								))}
							</select>
						</form>
					) : (
						<span class="muted">{node?.name ?? 'Local'}</span>
					)}
				</td>
				<td>
					<span class={`badge badge-${job.status} job-status`}>{job.status}</span>
					{job.exit_code != null && job.exit_code !== 0 && (
						<span class="badge badge-error">exit {job.exit_code}</span>
					)}
				</td>
				<td class="actions-col">
					{job.status === 'pending' && (
						<form method="post" action={`/execute/job/${job.id}/run`} style="display:inline">
							<button type="submit" data-size="sm">▶ Run</button>
						</form>
					)}
					{job.status === 'pending' && (
						<form method="post" action={`/execute/job/${job.id}/cancel`} style="display:inline">
							<button type="submit" class="secondary" data-size="sm">✕</button>
						</form>
					)}
					{(job.status === 'done' || job.status === 'error') && job.output && (
						<button
							data-size="sm"
							class="secondary"
							onclick={`document.getElementById('job-log-${job.id}').toggleAttribute('hidden')`}
						>
							Log
						</button>
					)}
				</td>
			</tr>
			{job.output && (
				<tr>
					<td colspan={6} style="padding:0;">
						<div id={`job-log-${job.id}`} hidden class="log-output">{job.output}</div>
					</td>
				</tr>
			)}
		</>
	);
};
