<script lang="ts">
  import { solve } from '$lib/engine';
  import type { CalculatorDef } from '$lib/data/calculators';
  import { page } from '$app/stores';
  import { onMount } from 'svelte';
  import { browser } from '$app/environment';
  import QuickDefinitionCard from '$lib/components/QuickDefinitionCard.svelte';
  import QuickConversionExample from '$lib/components/QuickConversionExample.svelte';
  import QuickConversionTable from '$lib/components/QuickConversionTable.svelte';

  export let config: CalculatorDef;
  export let showTitle = true;

  let val1 = '';
  let val2 = '';
  let val3 = '';
  let activeField: 1 | 2 | 3 = 1;
  let swapState: { originalField: 1 | 2; originalValue: string } | null = null;
  let copyStatus: 'idle' | 'copied' | 'failed' = 'idle';
  let statusTimeout: ReturnType<typeof setTimeout> | null = null;
  let copyStatusMessage = '';
  let hasInputs = false;

  $: has3 = ['3col', '3col-mul'].includes(config.type) || !!config.labels.in3;
  $: isTextInput = ['base', 'text-bin', 'bin-text', 'dec-frac', 'dms-dd', 'dd-dms'].includes(config.type);

  // Clear inputs on config (route) change
  $: if (config) {
    if (!paramsInitializing) clear();
  }

  let paramsInitializing = true;

  function handleInput(source: 1 | 2 | 3, options?: { preserveSwap?: boolean }) {
    if (!options?.preserveSwap) {
      swapState = null;
    }
    activeField = source;
    const result = solve(config, source, val1, val2, val3);
    if (source !== 1) val1 = result.val1;
    if (source !== 2) val2 = result.val2;
    if (source !== 3) val3 = result.val3;
  }

  function swap() {
    if (!swapState) {
      const manualField: 1 | 2 = activeField === 1 ? 1 : 2;
      const manualValue = manualField === 1 ? val1 : val2;
      const targetField: 1 | 2 = manualField === 1 ? 2 : 1;
      swapState = { originalField: manualField, originalValue: manualValue };
      if (targetField === 1) val1 = manualValue;
      else val2 = manualValue;
      handleInput(targetField, { preserveSwap: true });
      return;
    }

    const manualField = swapState.originalField;
    const manualValue = swapState.originalValue;
    if (manualField === 1) val1 = manualValue;
    else val2 = manualValue;
    swapState = null;
    handleInput(manualField, { preserveSwap: true });
  }

  function clear() {
    val1 = '';
    val2 = '';
    val3 = '';
    swapState = null;
  }

  function buildShareUrl() {
    const params = new URLSearchParams();
    if (val1.trim()) {
      params.set('v1', val1);
    }
    if (val2.trim()) {
      params.set('v2', val2);
    }
    if (val3.trim() && has3) {
      params.set('v3', val3);
    }

    const shareUrl = new URL($page.url);
    shareUrl.search = params.toString();
    return shareUrl.toString();
  }

  async function copyLink() {
    if (!browser) return;
    const url = buildShareUrl();

    try {
      await navigator.clipboard.writeText(url);
      copyStatus = 'copied';
    } catch (error) {
      console.error('Failed to copy link', error);
      copyStatus = 'failed';
    } finally {
      if (statusTimeout) {
        clearTimeout(statusTimeout);
      }
      statusTimeout = setTimeout(() => {
        copyStatus = 'idle';
      }, 2000);
    }
  }

  $: hasInputs =
    Boolean(
      val1.trim() ||
        val2.trim() ||
        (has3 && val3.trim())
    );
  $: copyStatusMessage =
    copyStatus === 'copied'
      ? 'Link copied to clipboard'
      : copyStatus === 'failed'
        ? 'Failed to copy link'
        : '';

  onMount(() => {
    const params = new URLSearchParams($page.url.search);
    if (params.has('v1')) { val1 = params.get('v1')!; handleInput(1); }
    else if (params.has('v2')) { val2 = params.get('v2')!; handleInput(2); }
    else if (params.has('v3') && has3) { val3 = params.get('v3')!; handleInput(3); }
    setTimeout(() => { paramsInitializing = false; }, 0);
  });
</script>

<div class="calculator-card">
  {#if showTitle || config.teaser}
    <div class="calc-header">
      {#if showTitle}
        <h2>{config.name}</h2>
      {/if}
      {#if config.teaser}
        <p class="calc-subtitle" class:no-title={!showTitle}>{config.teaser}</p>
      {/if}
    </div>
  {/if}

  <div class="calc-body" class:three-col={has3}>
    <div class="input-group">
      <label for="calc-in1">{config.labels.in1}</label>
      <input
        id="calc-in1"
        type={isTextInput ? 'text' : 'number'}
        bind:value={val1}
        on:input={() => handleInput(1)}
        placeholder="Enter value"
        class:active={activeField === 1}
      />
    </div>

    {#if !has3}
      <div class="swap-col">
        <button
          type="button"
          class="swap-btn"
          on:click={swap}
          title="Swap values"
          aria-label="Swap conversion direction"
        >
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M7 16l-4-4 4-4M17 8l4 4-4 4M3 12h18" />
          </svg>
        </button>
      </div>
    {/if}

    <div class="input-group">
      <label for="calc-in2">{config.labels.in2}</label>
      <input
        id="calc-in2"
        type={isTextInput ? 'text' : 'number'}
        bind:value={val2}
        on:input={() => handleInput(2)}
        placeholder={has3 ? 'Enter value' : 'Result'}
        class:active={activeField === 2}
      />
    </div>

    {#if has3}
      <div class="input-group result-group">
        <label for="calc-in3">{config.labels.in3}</label>
        <input
          id="calc-in3"
          type="number"
          bind:value={val3}
          on:input={() => handleInput(3)}
          placeholder="Result"
          class:active={activeField === 3}
        />
      </div>
    {/if}
  </div>

  <div class="calc-footer">
    <div class="footer-controls">
      <button type="button" class="clear-btn" on:click={clear} aria-label="Clear calculator inputs">
        Clear
      </button>
      <button
        type="button"
        class="icon-btn"
        on:click={copyLink}
        aria-label="Copy calculator link"
        disabled={!hasInputs}
      >
        <svg viewBox="0 0 24 24" role="presentation" aria-hidden="true">
          <path
            d="M10 14a1 1 0 0 1-1 1H6a4 4 0 0 1 0-8h3a1 1 0 1 1 0 2H6a2 2 0 0 0 0 4h3a1 1 0 0 1 1 1zm4-2a1 1 0 0 1 1-1h3a2 2 0 0 0 0-4h-3a1 1 0 1 1 0-2h3a4 4 0 0 1 0 8h-3a1 1 0 0 1-1-1zm-1.293 2.293a1 1 0 0 1 1.414 1.414l-4 4a1 1 0 0 1-1.414-1.414l4-4zM12 16l-4-4 4-4"
            fill="none"
            stroke="currentColor"
            stroke-width="1.6"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
        </svg>
      </button>
      <span class="sr-only" aria-live="polite">
        {copyStatusMessage}
      </span>
    </div>
    {#if config.factor && config.type === 'standard'}
      <span class="formula-hint">
        1 {config.labels.in1} = {config.factor}{config.offset ? ` + ${config.offset}` : ''} {config.labels.in2}
      </span>
    {/if}
  </div>
  <QuickConversionTable {config} />
  <QuickConversionExample {config} />
  <QuickDefinitionCard {config} />
</div>

<style>
  .calculator-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 16px;
    overflow: hidden;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
    transition: box-shadow 0.3s ease;
  }
  .calculator-card:hover {
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.18);
  }

  .calc-header {
    padding: 1.5rem 2rem 1rem;
    border-bottom: 1px solid var(--border);
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
  }
  .calc-header h2 {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 600;
    color: #fff;
    letter-spacing: -0.01em;
  }
  .calc-subtitle {
    margin: 0.35rem 0 0;
    font-size: 0.9rem;
    color: rgba(255, 255, 255, 0.85);
    font-weight: 400;
  }
  .calc-subtitle.no-title {
    margin-top: 0;
  }

  .calc-body {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 1rem;
    padding: 2rem;
    align-items: end;
  }
  .calc-body.three-col {
    grid-template-columns: 1fr 1fr 1fr;
  }

  .input-group {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }
  .input-group label {
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
  }
  .input-group input {
    padding: 0.85rem 1rem;
    border: 2px solid var(--border);
    border-radius: 10px;
    background: var(--input-bg);
    color: var(--text);
    font-family: 'JetBrains Mono', monospace;
    font-size: 1.1rem;
    transition: border-color 0.2s, box-shadow 0.2s;
    width: 100%;
    box-sizing: border-box;
  }
  .input-group input:focus,
  .input-group input.active {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-glow);
  }
  .input-group input::placeholder {
    color: var(--text-muted);
    opacity: 0.5;
  }

  /* Hide number spinners */
  .input-group input[type='number']::-webkit-inner-spin-button,
  .input-group input[type='number']::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
  .input-group input[type='number'] {
    -moz-appearance: textfield;
  }

  .swap-col {
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 1.2rem;
  }
  .swap-btn {
    background: var(--accent);
    color: #fff;
    border: none;
    border-radius: 50%;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.2s, background 0.2s;
  }
  .swap-btn:hover {
    background: var(--accent-dark);
    transform: rotate(180deg);
  }
  .swap-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-glow);
  }

  .calc-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 2rem 1.25rem;
    border-top: 1px solid var(--border);
  }
  .footer-controls {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    position: relative;
  }

  .clear-btn {
    padding: 0.5rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.85rem;
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
  }
  .clear-btn:hover {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
  }
  .clear-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-glow);
  }
  .icon-btn {
    width: 40px;
    height: 40px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--section-bg);
    color: var(--text);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
  }
  .icon-btn svg {
    width: 1.1rem;
    height: 1.1rem;
  }
  .icon-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  .icon-btn:not(:disabled):hover {
    border-color: var(--accent);
    background: var(--surface-hover);
  }
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .formula-hint {
    font-size: 0.78rem;
    color: var(--text-muted);
    font-family: 'JetBrains Mono', monospace;
  }

  @media (max-width: 900px) {
    .calc-footer {
      flex-wrap: wrap;
      gap: 0.75rem;
    }
    .formula-hint {
      width: 100%;
    }
  }

  @media (max-width: 640px) {
    .calc-header {
      padding: 1.2rem 1.2rem 0.9rem;
    }
    .calc-body {
      grid-template-columns: 1fr;
      gap: 0.75rem;
      padding: 1.25rem;
    }
    .calc-body.three-col {
      grid-template-columns: 1fr;
    }
    .swap-col {
      padding-top: 0;
    }
    .swap-btn {
      transform: rotate(90deg);
    }
    .swap-btn:hover {
      transform: rotate(270deg);
    }
    .calc-footer {
      padding: 0.9rem 1.25rem 1rem;
    }
  }
</style>
