<script lang="ts">
  import { slide } from 'svelte/transition'
  import { quintOut } from 'svelte/easing'
  import { createEventDispatcher } from 'svelte'
  import {
    createDedicatedSizingStores,
    MAX_TOTAL_QPS,
    MAX_CUSTOMER_DATA_VOLUME_TB,
    MAX_REPLICA,
    MAX_COMPRESSION_RATIO,
    MAX_REDUCTION_PERCENT,
    WorkloadTypes,
  } from '$lib/stores/dedicated-sizing'
  import FormItem from '$lib/comps/FormItem.svelte'
  import NumInput from '$lib/comps/NumInput.svelte'

  import SizingExplain from './SizingExplain.svelte'
  import SizingNodeCell from './SizingNodeCell.svelte'

  const dispatch = createEventDispatcher()

  export let offsetRight = 680
  export let visible = false
  export let data: ReturnType<typeof createDedicatedSizingStores> | null = null
  export let curTiDBTiKVNodeSpec: {
    tidb: {
      specLong: string | number | undefined
      nodes: number
    }
    tikv: {
      specLong: string | number | undefined
      nodes: number
    }
  }

  let explainExpend: any = null

  $: totalQPS = data?.totalQPS
  $: workloadType = data?.workloadType
  $: dataVolumeTB = data?.dataVolumeTB
  $: replica = data?.replica
  $: storageWaterLevelPercent = data?.storageWaterLevelPercent
  $: compress = data?.compress || createDedicatedSizingStores().compress

  const handleClose = () => {
    dispatch('close')
  }

  const handleExplain = (data: any) => {
    explainExpend = data
  }
</script>

{#if visible && data}
  <div
    transition:slide={{ delay: 300, duration: 200, easing: quintOut, axis: 'x' }}
    class={`fixed top-8 bottom-0 w-[540px] bg-gryl-50 shadow-drawer flex flex-col rounded-l-xl py-8`}
    style="right: {offsetRight}px"
  >
    <div class="flex justify-between mx-8 shrink-0 item-center">
      <div class="flex item-center">
        <img src="/sizing.svg" alt="config icon" class="block mr-3 h-7 w-7" />
        <div class="text-xl font-semibold text-gry-900">Size Estimation</div>
      </div>

      <button class="flex items-center justify-center w-8 h-8" on:click={handleClose}>
        <div class="transition text-gry-400 hover:text-gry-900">
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M19 5L5 19"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
            <path
              d="M19 19L5 5"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
          </svg>
        </div>
      </button>
    </div>
    <div class="shrink-0 h-[1px] bg-gryl-100 mt-6 mb-6 mx-8" />

    <div class="relative flex-grow w-full">
      <div class="absolute inset-0 px-8 overflow-y-auto">
        <div class="w-full text-xs text-alert-600">
          <span class="inline-block w-1 h-1 mr-1 align-middle rounded-lg bg-alert-500" />
          This result is a starting point of the cluster size, you should validate the sizing provided
          by the tool by doing a POC test and adjust the sizing based on the specific workload testing.
        </div>
        <div class="w-full mt-2 text-xs text-alert-600">
          <span class="inline-block w-1 h-1 mr-1 align-middle rounded-lg bg-alert-500" />
          If node num is more than 50, the result may be unreliable or even meaningless(marked as 'N/A')!
        </div>
        <div class="w-full mt-2 text-xs text-alert-600">
          <span class="inline-block w-1 h-1 mr-1 align-middle rounded-lg bg-alert-500" />
          Reference Doc:
          <a
            href="https://pingcap.feishu.cn/wiki/wikcnBXFC4pAFYkfzmdbBBX2cHe"
            target="_blank"
            class="underline transition text-prm-400 underline-offset-2 decoration-dashed hover:text-prm-600"
            >TiDBCloud Cluster Size Estimation Model</a
          >
        </div>

        <div class="mt-10">
          <div class="text-gry-900 font-bold text-[18px]">Performance Requirement</div>
          <div class="flex justify-between mt-4">
            <div class="mr-3 w-[calc((100%-12px)/2)] shrink-0">
              <FormItem label="Total QPS" required>
                <NumInput bind:value={$totalQPS} min={1} max={MAX_TOTAL_QPS} step={100} />
              </FormItem>
            </div>
            <div class="grow shrink-0">
              <FormItem label="Workload" required>
                <select
                  class="flex items-center w-full h-10 pl-4 pr-12 transition-all transform bg-white bg-no-repeat border rounded-lg appearance-none border-gryl-200 text-gry-900"
                  style="background-image:url('/arrow-sm-down.svg');background-size: 24px 24px;background-position: top 8px right 12px;"
                  bind:value={$workloadType}
                >
                  <option value="write">Write</option>
                  <option value="read">Read</option>
                  <option value="mixed">Mixed</option>
                  <option value="point_select">Point-Select</option>
                </select>
              </FormItem>
            </div>
          </div>
        </div>

        <div class="mt-10">
          <div class="text-gry-900 font-bold text-[18px]">Storage Requirement</div>
          <div class="flex justify-between mt-4">
            <div class="mr-3 w-[calc((100%-12px)/2)] shrink-0">
              <FormItem label="Customer Data Volume (TB)" required>
                <NumInput
                  bind:value={$dataVolumeTB}
                  min={1}
                  max={MAX_CUSTOMER_DATA_VOLUME_TB}
                  step={5}
                />
              </FormItem>
            </div>
            <div class="grow shrink-0">
              <FormItem label="Replica" required>
                <NumInput bind:value={$replica} min={1} max={MAX_REPLICA} step={1} />
              </FormItem>
            </div>
          </div>

          <div class="flex justify-between mt-4">
            <FormItem label="Storage Water Level (%)" required hasTips>
              <div slot="tips">percentage of how much storage is expected to be used</div>
              <div class="w-[calc((100%-12px)/2)] shrink-0">
                <NumInput bind:value={$storageWaterLevelPercent} min={0} max={100} step={5} />
              </div>
            </FormItem>
          </div>

          <div class="flex justify-between mt-4">
            <FormItem label="Data Compress" required>
              <div class="flex items-center w-full">
                <div class="w-[calc((100%-12px)*0.6)] shrink-0 mr-3">
                  <select
                    class="flex items-center w-full h-10 pl-4 pr-12 transition-all transform bg-white bg-no-repeat border rounded-lg appearance-none border-gryl-200 text-gry-900"
                    style="background-image:url('/arrow-sm-down.svg');background-size: 24px 24px;background-position: top 8px right 12px;"
                    bind:value={$compress.param}
                  >
                    <option value="compression_ratio">Compression Ratio</option>
                    <option value="reduction_percent">Reduction Percent (%)</option>
                  </select>
                </div>
                <div class="grow">
                  {#if $compress.param === 'compression_ratio'}
                    <NumInput
                      bind:value={$compress.ratio}
                      min={1}
                      max={MAX_COMPRESSION_RATIO}
                      step={0.1}
                    />
                  {:else if $compress.param === 'reduction_percent'}
                    <NumInput
                      bind:value={$compress.reductionPercent}
                      min={0}
                      max={MAX_REDUCTION_PERCENT}
                      step={1}
                    />
                  {/if}
                </div>
              </div>
            </FormItem>
          </div>
          <div class="flex items-center mt-3 ml-1 text-xs poppins text-gry-300">
            This means&nbsp;<span class="font-bold text-prm-600">1 GiB</span>&nbsp;data will be
            compressed to&nbsp;
            <span class="font-bold text-prm-600"
              >{$compress.param === 'compression_ratio'
                ? Math.ceil((1 / Number($compress.ratio)) * 100) / 100
                : Math.ceil(100 - Number($compress.reductionPercent)) / 100} GiB</span
            >
          </div>
        </div>

        <div class="mt-10">
          <div class="text-gry-900 font-bold text-[18px] flex items-center shrink-0">
            <span class="text-prm-600">TiDB&nbsp;</span> Estimation Result
            <div class="h-[1px] grow rounded bg-gryl-200 ml-3" />
          </div>
          <div class="mt-2">
            <div class="flex px-1 py-4 text-xs font-medium leading-3 text-gry-400">
              <div class="shrink-0 w-[128px]">
                Latency({WorkloadTypes.find((it) => it.value === $workloadType)?.label || '-'})
              </div>
              <div class="grow shrink-0 w-[160px]">8 vCPU, 16 GiB</div>
              <div class="grow shrink-0 w-[160px]">16 vCPU, 32 GiB</div>
            </div>

            <div class="flex items-center px-1 py-2 mb-1 text-sm">
              <div class="shrink-0 w-[128px] text-gry-900 font-semibold">
                P95≈{$workloadType === 'point_select' ? 5 : 100}ms
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p95100ms"
                  spec="8C16G"
                  type="tidb"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p95100ms"
                  spec="16C32G"
                  type="tidb"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
            </div>

            {#if explainExpend?.type === 'tidb' && explainExpend?.perf === 'p95100ms'}
              <div transition:slide class="py-2 mb-3 text-sm">
                <SizingExplain
                  perf="p95100ms"
                  type="tidb"
                  {data}
                  spec={explainExpend?.spec}
                  on:close={() => (explainExpend = null)}
                />
              </div>
            {/if}

            <div class="flex items-center px-1 py-2 mb-1 text-sm">
              <div class="shrink-0 w-[128px] text-gry-900 font-semibold">
                P99≈{$workloadType === 'point_select' ? 10 : 300}ms
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99300ms"
                  spec="8C16G"
                  type="tidb"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99300ms"
                  spec="16C32G"
                  type="tidb"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
            </div>

            {#if explainExpend?.type === 'tidb' && explainExpend?.perf === 'p99300ms'}
              <div transition:slide class="py-2 mb-3 text-sm">
                <SizingExplain
                  perf="p99300ms"
                  type="tidb"
                  {data}
                  spec={explainExpend?.spec}
                  on:close={() => (explainExpend = null)}
                />
              </div>
            {/if}

            <div class="flex items-center px-1 py-2 mb-1 text-sm">
              <div class="shrink-0 w-[128px] text-gry-900 font-semibold">
                P99≈{$workloadType === 'point_select' ? 5 : 100}ms
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99100ms"
                  spec="8C16G"
                  type="tidb"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99100ms"
                  spec="16C32G"
                  type="tidb"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
            </div>

            {#if explainExpend?.type === 'tidb' && explainExpend?.perf === 'p99100ms'}
              <div transition:slide class="py-2 mb-3 text-sm">
                <SizingExplain
                  perf="p99100ms"
                  type="tidb"
                  {data}
                  spec={explainExpend?.spec}
                  on:close={() => (explainExpend = null)}
                />
              </div>
            {/if}
          </div>
        </div>

        <div class="mt-10">
          <div class="text-gry-900 font-bold text-[18px] flex items-center shrink-0">
            <span class="text-prm-600">TiKV&nbsp;</span> Estimation Result
            <div class="h-[1px] grow rounded bg-gryl-200 ml-3" />
          </div>
          <div class="mt-2">
            <div class="flex px-1 py-4 text-xs font-medium leading-3 text-gry-400">
              <div class="shrink-0 w-[128px]">
                Latency({WorkloadTypes.find((it) => it.value === $workloadType)?.label || '-'})
              </div>
              <div class="grow shrink-0 w-[160px]">8 vCPU, 32 GiB</div>
              <div class="grow shrink-0 w-[160px]">16 vCPU, 64 GiB</div>
            </div>

            <div class="flex items-center px-1 py-2 mb-1 text-sm">
              <div class="shrink-0 w-[128px] text-gry-900 font-semibold">
                P95≈{$workloadType === 'point_select' ? 5 : 100}ms
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p95100ms"
                  spec="8C32G"
                  type="tikv"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p95100ms"
                  spec="16C64G"
                  type="tikv"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
            </div>

            {#if explainExpend?.type === 'tikv' && explainExpend?.perf === 'p95100ms'}
              <div transition:slide class="py-2 mb-3 text-sm">
                <SizingExplain
                  perf="p95100ms"
                  type="tikv"
                  {data}
                  spec={explainExpend?.spec}
                  on:close={() => (explainExpend = null)}
                />
              </div>
            {/if}

            <div class="flex items-center px-1 py-2 mb-1 text-sm">
              <div class="shrink-0 w-[128px] text-gry-900 font-semibold">
                P99≈{$workloadType === 'point_select' ? 10 : 300}ms
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99300ms"
                  spec="8C32G"
                  type="tikv"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99300ms"
                  spec="16C64G"
                  type="tikv"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
            </div>

            {#if explainExpend?.type === 'tikv' && explainExpend?.perf === 'p99300ms'}
              <div transition:slide class="py-2 mb-3 text-sm">
                <SizingExplain
                  perf="p99300ms"
                  type="tikv"
                  {data}
                  spec={explainExpend?.spec}
                  on:close={() => (explainExpend = null)}
                />
              </div>
            {/if}

            <div class="flex items-center px-1 py-2 mb-1 text-sm">
              <div class="shrink-0 w-[128px] text-gry-900 font-semibold">
                P99≈{$workloadType === 'point_select' ? 5 : 100}ms
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99100ms"
                  spec="8C32G"
                  type="tikv"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
              <div class="grow shrink-0 w-[160px]">
                <SizingNodeCell
                  perf="p99100ms"
                  spec="16C64G"
                  type="tikv"
                  {data}
                  {explainExpend}
                  {curTiDBTiKVNodeSpec}
                  on:explain={(e) => handleExplain(e.detail)}
                  on:pick
                />
              </div>
            </div>

            {#if explainExpend?.type === 'tikv' && explainExpend?.perf === 'p99100ms'}
              <div transition:slide class="py-2 mb-3 text-sm">
                <SizingExplain
                  perf="p99100ms"
                  type="tikv"
                  {data}
                  spec={explainExpend?.spec}
                  on:close={() => (explainExpend = null)}
                />
              </div>
            {/if}
          </div>
        </div>
      </div>
    </div>
  </div>
{/if}
