<script lang="ts" context="module">
  interface DeletionSideEffect {
    name: string
    op: string  
  }
</script>

<script lang="ts">
  import { goto } from "$app/navigation";
import { getStores } from "$app/stores";

  import { sl3 } from "$lib/clients/sl3";
  import Modal from "$lib/components/common/Modal.svelte";
  import ModalBody from "$lib/components/common/ModalBody.svelte";
  import { getItemListContext } from "$lib/components/contexts/ItemListContext.svelte";
  import { getItemMultiListContext } from "$lib/components/contexts/ItemMultiListContext.svelte";
  import { getModalContext } from "$lib/components/contexts/ModalContext.svelte";
  import { getProjectContext } from "$lib/components/contexts/ProjectContext.svelte";
  import { getProjectListContext } from "$lib/components/contexts/ProjectListContext.svelte";
  import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte";
  import { getSprintListContext } from "$lib/components/contexts/SprintListContext.svelte";
  import type Stat from "$lib/models/stat";
  import { scopePrettyId } from "$lib/utils/prettyIds";

  const {currentModal, closeModal} = getModalContext();
  const {scope, deleteStat} = getScopeContext();
  const {project, reloadProject} = getProjectContext();
  const {reloadProjectList} = getProjectListContext();
  const {reloadSprintList} = getSprintListContext();
  const {reloadItemList} = getItemListContext();
  const {reloadItemLists} = getItemMultiListContext();
  const {page} = getStores();

  let endpoint: string;

  let error: string
  let loading: boolean;
  let show: boolean;
  let noun: string;
  let sideEffects: DeletionSideEffect[];
  let name: string;
  let dangerZone: boolean;
  let dangerZoneConfirm: string;
  let navigate: string;

  $: switch ($currentModal.name) {
    case "scope.delete":
      init("", [{op: "Delete", name: "everything under the scope."}])
      noun = "Scope";
      name = $currentModal.scope.name;
      dangerZone = true;
      navigate = "/";
      break;

    case "item.delete":
      init(`items/${$currentModal.item.id}`, [], $currentModal.item.scopeId)
      noun = "Item";
      name = $currentModal.item.name;
      break;

    case "stat.delete":
      init(`stats/${$currentModal.stat.id}`)
      noun = "Stat";
      name = $currentModal.stat.name;
      dangerZone = true;
      break;

    case "sprint.delete":
      init(`sprints/${$currentModal.sprint.id}`, [], $currentModal.sprint.scopeId)
      noun = "Sprint";
      name = $currentModal.sprint.name;
      break;

    case "requirement.delete":
      init(`projects/${$project.id}/requirements/${$currentModal.requirement.id}`,
        $currentModal.requirement.items.map(i => ({
          op: "Detach item",
          name: i.name,
        })),
      );
      noun = "Requirement";
      name = $currentModal.requirement.name;
      break;

    case "project.delete":
      init(`projects/${$currentModal.project.id}`,
        $currentModal.project.requirements.flatMap(r => ([{
          op: "Delete requirement",
          name: `${r.name} (${r.statusName})`,
        }, ...r.items.map(i => ({
          op: "Detach item",
          name: i.name,
        }))]))
      )
      noun = "Project";
      name = $currentModal.project.name;
      dangerZone = true;
      navigate = `/${scopePrettyId($scope)}`;
      break;

    default:
      loading = false;
      error = null;
      show = false;
  }

  function init(newEndpoint: string, newSideEffects: DeletionSideEffect[] = [], overrideScopeId?: number) {
    let scopeId = $scope.id;
    if (overrideScopeId != null) {
      scopeId = overrideScopeId;
    }

    endpoint = `scopes/${scopeId}/${newEndpoint}`;
    if (endpoint.endsWith("/")) {
      endpoint = endpoint.slice(0, -1);
    }
    sideEffects = newSideEffects;
    show = true;
    error = null;
    dangerZone = false;
    dangerZoneConfirm = "";
    navigate = null;
  }

  async function submit() {
    error = null;
    loading = true;

    try {
      const res = await sl3(fetch, $page.stuff.idToken).fetch("DELETE", endpoint);
    
      if (navigate) {
        if (noun === "Project") {
          await reloadProjectList();
        }

        goto(navigate);
      } else {
        // Wait for project reload if it's updating a project
        await reloadProject();

        if (noun === "Stat") {
          reloadItemLists();
          deleteStat((res as {stat: Stat}).stat);
        }

        if (noun === "Sprint") {
          await reloadSprintList();
        }

        if (noun === "Item") {
          reloadItemLists();
          await reloadItemList();
        }
  
        // TODO: History context upsert
      }

      closeModal();
    } catch(err) {
      if (err.statusCode != null) {
        error = err.statusMessage;
      } else {
        error = err
      }

    } finally {
      loading = false;
    }
  }

  let disabled;
  $: disabled = loading || (!!dangerZone && name !== dangerZoneConfirm)
</script>

<form on:submit|preventDefault={submit}>
  <Modal closable show={show} verb="Delete" noun={noun} disabled={disabled} error={error}>
    <ModalBody>
      <p>Are you sure you want to delete this {noun.toLocaleLowerCase()}?</p>
      {#if sideEffects.length > 0}
        <p>There are side-effects to this deletion.</p>
        <ul>
          {#each sideEffects as sideEffect}
            <li>{sideEffect.op} {sideEffect.name}</li>
          {/each}
        </ul>
      {/if}
      <label for="name">{noun} name</label>
      <input type="text" disabled name="name" value={name} />
      {#if dangerZone}
        <label for="confirm">Re-type name to confirm</label>
        <input type="text" name="confirm" bind:value={dangerZoneConfirm} />
      {/if}
    </ModalBody>
  </Modal>
</form>