<script setup>
import Button from "primevue/button";
import Dropdown from "primevue/dropdown";
import InputNumber from "primevue/inputnumber";
import InputText from "primevue/inputtext";
import Message from "primevue/message";
import BaseButton from "../../../components/base/BaseButton.vue";
import { WEEKDAYS as WEEKDAY_KEYS, fetchTasks } from "../composables/useHoursApi.js";
import strings from "../strings.js";

const props = defineProps({
  loading: { type: Boolean, default: false },
  saving: { type: Boolean, default: false },
  weekLocked: { type: Boolean, default: false },
  registry: { type: Object, required: true },
  registryHelpVisible: { type: Boolean, default: false },
  week: { type: Object, default: null },
  lines: {
    /** @type {import('vue').PropType<Array<Record<string, unknown>>>} */
    type: Array,
    required: true,
  },
});

defineEmits(["persist", "submit", "add-internal", "add-customer", "add-project", "remove"]);

const typeOptions = [
  { label: "Internal", value: "internal" },
  { label: "Customer", value: "customer" },
  { label: "Project", value: "project" },
  { label: "Task", value: "task" },
];

const weekdayLabels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];

function hasInternalCategories() {
  return Array.isArray(props.registry?.internalCategories) && props.registry.internalCategories.length > 0;
}

function hasCustomers() {
  return Array.isArray(props.registry?.customers) && props.registry.customers.length > 0;
}

function hasProjects() {
  return Array.isArray(props.registry?.projects) && props.registry.projects.length > 0;
}

async function ensureTaskOptions(line) {
  if (line.registration_type !== "task") {
    return;
  }

  const pid =
    /** @type {number | null} */ (line._uiProjectForTasks) ??
    /** @type {number | null} */ (line.task_hour_project_id ?? null);

  if (!pid) {
    line._taskPickList = [];

    return;
  }

  try {
    line._taskPickList = await fetchTasks(pid);
  } catch {
    line._taskPickList = [];
  }
}

async function onLineRegistrationTypeCommit(line) {
  if (line.registration_type === "internal" && hasInternalCategories()) {
    line.internal_category_id = props.registry.internalCategories[0].id;
    line.customer_id = null;
    line.hour_project_id = null;
    line.hour_task_id = null;

    await ensureTaskOptions(line);

    return;
  }

  if (line.registration_type === "customer" && hasCustomers()) {
    line.customer_id = props.registry.customers[0].id;
    line.internal_category_id = null;
    line.hour_project_id = null;
    line.hour_task_id = null;

    await ensureTaskOptions(line);

    return;
  }

  if (line.registration_type === "project" && hasProjects()) {
    line.hour_project_id = props.registry.projects[0].id;
    line.hour_task_id = null;
    line.internal_category_id = null;
    line.customer_id = null;

    await ensureTaskOptions(line);

    return;
  }

  if (line.registration_type === "task" && hasProjects()) {
    line.hour_task_id = null;
    line.internal_category_id = null;
    line.customer_id = null;
    line.hour_project_id = null;
    line._uiProjectForTasks =
      /** @type {number | null} */ (line.task_hour_project_id ?? null) ?? props.registry.projects[0].id;

    await ensureTaskOptions(line);
  }
}

async function onTaskProjectChange(line, projectIdMaybe) {
  line._uiProjectForTasks = projectIdMaybe;
  line.hour_task_id = null;
  await ensureTaskOptions(line);
}
</script>

<template>
  <div>
    <Message v-if="registryHelpVisible" severity="info" class="mb-4" :closable="false">
      Hour registration has no targets yet. Configure at least one of: active internal categories, active CRM customers, or hour
      projects — e.g. run
      <code class="text-xs px-1">php artisan db:seed</code>
      (includes hour registration seeders), or ask an administrator to set up reference data.
    </Message>
    <div v-if="loading" class="py-8">
      Loading…
    </div>
    <div v-else class="surface-card border-round-lg shadow-2 p-3 overflow-auto">
      <div class="flex flex-wrap gap-2 mb-4">
        <BaseButton type="button" outlined size="small" icon="plus" label="Add internal" :disabled="weekLocked || !hasInternalCategories()"
          variant="secondary" @click="$emit('add-internal')" />
        <BaseButton type="button" outlined size="small" icon="plus" label="Add customer" :disabled="weekLocked || !hasCustomers()"
          variant="secondary" @click="$emit('add-customer')" />
        <BaseButton type="button" outlined size="small" icon="plus" label="Add project" :disabled="weekLocked || !hasProjects()"
          variant="secondary" @click="$emit('add-project')" />
        <BaseButton variant="secondary" outlined size="small" :loading="saving" :disabled="loading || weekLocked" :label="strings.save"
          @click="$emit('persist', true)" />
        <BaseButton variant="primary" size="small" :loading="saving" :disabled="loading || weekLocked" :label="strings.submit"
          @click="$emit('submit')" />
      </div>
      <div class="max-h-[min(70vh,48rem)] overflow-auto border border-surface-200 dark:border-surface-700 border-round-lg">
        <table class="w-full text-sm border-collapse">
          <thead class="sticky top-0 z-[1] bg-surface-0 dark:bg-surface-950 shadow-sm">
            <tr>
              <th class="text-left p-2 border-b border-surface-200 dark:border-surface-700">{{ strings.targetLabel }}</th>
              <th class="text-left p-2 border-b border-surface-200 dark:border-surface-700 w-[14rem] min-w-[8rem]">
                {{ strings.quickDescription }}
              </th>
              <th v-for="(lbl, ix) in weekdayLabels" :key="'h-' + lbl + ix" class="text-center p-2 border-b border-surface-200 dark:border-surface-700">
                {{ lbl }}
              </th>
              <th class="w-10 border-b border-surface-200 dark:border-surface-700" />
            </tr>
          </thead>
          <tbody>
            <tr v-for="(line, idx) in lines" :key="String(line.id ?? 'n-' + idx)" class="odd:bg-surface-50/70 dark:odd:bg-surface-900/35">
              <td class="align-top p-2 md:w-[18rem]">
                <Dropdown
                  v-model="line.registration_type"
                  class="mb-2 w-full"
                  option-label="label"
                  option-value="value"
                  :options="typeOptions"
                  :disabled="weekLocked"
                  @update:model-value="() => onLineRegistrationTypeCommit(line)"
                />

                <Dropdown
                  v-if="line.registration_type === 'internal'"
                  v-model="line.internal_category_id"
                  class="w-full"
                  option-label="name"
                  option-value="id"
                  :disabled="weekLocked"
                  :options="registry.internalCategories"
                />
                <Dropdown
                  v-else-if="line.registration_type === 'customer'"
                  v-model="line.customer_id"
                  class="w-full"
                  option-label="name"
                  option-value="id"
                  :disabled="weekLocked"
                  :options="registry.customers"
                />

                <div v-else-if="line.registration_type === 'project'" class="flex flex-column gap-2">
                  <Dropdown
                    v-model="line.hour_project_id"
                    class="w-full"
                    option-label="name"
                    option-value="id"
                    :disabled="weekLocked"
                    :options="registry.projects"
                  />
                </div>

                <div v-else-if="line.registration_type === 'task'" class="flex flex-column gap-2">
                  <Dropdown
                    :model-value="line._uiProjectForTasks ?? line.task_hour_project_id ?? null"
                    class="w-full"
                    option-label="name"
                    option-value="id"
                    placeholder="Project scope"
                    :disabled="weekLocked || !hasProjects()"
                    :options="registry.projects"
                    @update:model-value="(v) => onTaskProjectChange(line, v)"
                  />
                  <Dropdown
                    v-model="line.hour_task_id"
                    class="w-full"
                    option-label="title"
                    option-value="id"
                    :disabled="weekLocked || !line._taskPickList?.length"
                    :options="line._taskPickList ?? []"
                  />
                </div>
              </td>
              <td class="align-top p-2 border-surface-100 dark:border-surface-800">
                <InputText v-model="line.description" fluid class="w-full text-xs" maxlength="500" :disabled="weekLocked" />
              </td>
              <td v-for="d in WEEKDAY_KEYS" :key="'c-' + d + idx" class="p-1 border-surface-100 dark:border-surface-800 align-top">
                <InputNumber
                  v-model="line.durations[d]"
                  class="max-w-[5.75rem]"
                  suffix=" h"
                  locale="en-US"
                  mode="decimal"
                  :min="0"
                  :max-fraction-digits="2"
                  :disabled="weekLocked"
                />
              </td>
              <td class="p-2 text-center align-top">
                <Button type="button" outlined size="small" severity="danger" icon="pi pi-times" :disabled="weekLocked"
                  @click="$emit('remove', idx)" />
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <p v-if="lines.length === 0" class="mt-4 text-muted-color">
        Add at least one row.
      </p>
    </div>
  </div>
</template>
