<script setup>
import { ref, watch, computed } from "vue";
import axios from "axios";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/Components/ui/dialog";
import { router, usePage } from "@inertiajs/vue3";
import { useForm, Field as FormField } from "vee-validate";
import { toTypedSchema } from "@vee-validate/zod";
import * as z from "zod";
import { FormControl, FormItem, FormLabel, FormMessage } from "@/Components/ui/form";
import { Input } from "@/Components/ui/input";
import { Textarea } from "@/Components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/Components/ui/select";
import { Switch } from "@/Components/ui/switch";
import { Button } from "@/Components/ui/button";

const props = defineProps({
  show: { type: Boolean, default: false },
  phone: Object,
  clientCaseUuid: { type: String, default: null },
  smsProfiles: { type: Array, default: () => [] },
  smsSenders: { type: Array, default: () => [] },
  smsTemplates: { type: Array, default: () => [] },
});

const emit = defineEmits(["close"]);

const page = usePage();
const pageProps = computed(() => page?.props ?? {});

const pageSmsProfiles = computed(() => {
  const fromProps =
    Array.isArray(props.smsProfiles) && props.smsProfiles.length
      ? props.smsProfiles
      : null;
  return fromProps ?? pageProps.value?.sms_profiles ?? [];
});

const pageSmsSenders = computed(() => {
  const fromProps =
    Array.isArray(props.smsSenders) && props.smsSenders.length ? props.smsSenders : null;
  return fromProps ?? pageProps.value?.sms_senders ?? [];
});

const pageSmsTemplates = computed(() => {
  const fromProps =
    Array.isArray(props.smsTemplates) && props.smsTemplates.length
      ? props.smsTemplates
      : null;
  return fromProps ?? pageProps.value?.sms_templates ?? [];
});

// SMS encoding helpers
const GSM7_EXTENDED = new Set(["^", "{", "}", "\\", "[", "~", "]", "|"]);

const isGsm7 = (text) => {
  for (const ch of text || "") {
    if (ch === "€") continue;
    const code = ch.charCodeAt(0);
    if (code >= 0x80) return false;
  }
  return true;
};

const gsm7Length = (text) => {
  let len = 0;
  for (const ch of text || "") {
    if (ch === "€" || GSM7_EXTENDED.has(ch)) {
      len += 2;
    } else {
      len += 1;
    }
  }
  return len;
};

const ucs2Length = (text) => (text ? text.length : 0);

const formatEu = (value, decimals = 2) => {
  if (value === null || value === undefined || value === "") {
    return new Intl.NumberFormat("de-DE", {
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    }).format(0);
  }
  const num =
    typeof value === "number"
      ? value
      : parseFloat(String(value).replace(/\./g, "").replace(",", "."));
  return new Intl.NumberFormat("de-DE", {
    minimumFractionDigits: decimals,
    maximumFractionDigits: decimals,
  }).format(isNaN(num) ? 0 : num);
};

const renderTokens = (text, vars) => {
  if (!text) return "";
  const resolver = (obj, path) => {
    if (!obj) return null;
    if (Object.prototype.hasOwnProperty.call(obj, path)) return obj[path];
    const segs = path.split(".");
    let cur = obj;
    for (const s of segs) {
      if (cur && typeof cur === "object" && s in cur) {
        cur = cur[s];
      } else {
        return null;
      }
    }
    return cur;
  };
  return text.replace(/\{([a-zA-Z0-9_\.]+)\}/g, (_, key) => {
    const val = resolver(vars, key);
    return val !== null && val !== undefined ? String(val) : `{${key}}`;
  });
};

const truncateToLimit = (text, limit, encoding) => {
  if (!text) return "";
  if (limit <= 0) return "";
  if (encoding === "UCS-2") {
    return text.slice(0, limit);
  }
  let acc = 0;
  let out = "";
  for (const ch of text) {
    const cost = ch === "€" || GSM7_EXTENDED.has(ch) ? 2 : 1;
    if (acc + cost > limit) break;
    out += ch;
    acc += cost;
  }
  return out;
};

// Form schema with custom validation
const formSchema = toTypedSchema(
  z.object({
    message: z
      .string()
      .min(1, "Vsebina sporočila je obvezna.")
      .refine(
        (val) => {
          const encoding = isGsm7(val) ? "GSM-7" : "UCS-2";
          const maxAllowed = encoding === "GSM-7" ? 640 : 320;
          const count = encoding === "GSM-7" ? gsm7Length(val) : ucs2Length(val);
          return count <= maxAllowed;
        },
        {
          message: "Sporočilo presega dovoljeno dolžino.",
        }
      ),
    template_id: z.number().nullable().optional(),
    contract_uuid: z.string().nullable().optional(),
    profile_id: z.number().nullable().optional(),
    sender_id: z.number().nullable().optional(),
    delivery_report: z.boolean().default(false),
  })
);

const form = useForm({
  validationSchema: formSchema,
  initialValues: {
    message: "",
    template_id: null,
    contract_uuid: null,
    profile_id: null,
    sender_id: null,
    delivery_report: false,
  },
});

const processing = ref(false);
const contractsForCase = ref([]);

const sendersForSelectedProfile = computed(() => {
  if (!form.values.profile_id) return pageSmsSenders.value;
  return (pageSmsSenders.value || []).filter(
    (s) => s.profile_id === form.values.profile_id
  );
});

const smsEncoding = computed(() => (isGsm7(form.values.message) ? "GSM-7" : "UCS-2"));

const charCount = computed(() =>
  smsEncoding.value === "GSM-7"
    ? gsm7Length(form.values.message)
    : ucs2Length(form.values.message)
);

const perSegment = computed(() => {
  const count = charCount.value;
  if (smsEncoding.value === "GSM-7") {
    return count <= 160 ? 160 : 153;
  }
  return count <= 70 ? 70 : 67;
});

const segments = computed(() => {
  const count = charCount.value;
  const size = perSegment.value || 1;
  return count > 0 ? Math.ceil(count / size) : 0;
});

const creditsNeeded = computed(() => segments.value);

const maxAllowed = computed(() => (smsEncoding.value === "GSM-7" ? 640 : 320));

const remaining = computed(() => Math.max(0, maxAllowed.value - charCount.value));

// Truncate message if exceeds limit
watch(
  () => form.values.message,
  (val) => {
    const limit = maxAllowed.value;
    if (charCount.value > limit) {
      form.setFieldValue("message", truncateToLimit(val, limit, smsEncoding.value));
    }
  }
);

// Auto-select sender when profile changes
watch(
  () => form.values.profile_id,
  (profileId) => {
    if (!profileId) {
      form.setFieldValue("sender_id", null);
      return;
    }

    const prof = (pageSmsProfiles.value || []).find((p) => p.id === profileId);
    if (prof?.default_sender_id) {
      const inList = sendersForSelectedProfile.value.find(
        (s) => s.id === prof.default_sender_id
      );
      if (inList) {
        form.setFieldValue("sender_id", prof.default_sender_id);
        return;
      }
    }

    // Auto-select first sender if available
    if (sendersForSelectedProfile.value.length > 0) {
      form.setFieldValue("sender_id", sendersForSelectedProfile.value[0].id);
    } else {
      form.setFieldValue("sender_id", null);
    }
  }
);

// Reset sender if not available for selected profile
watch(sendersForSelectedProfile, (list) => {
  if (!form.values.sender_id || !Array.isArray(list)) return;
  const ok = list.some((s) => s.id === form.values.sender_id);
  if (!ok) form.setFieldValue("sender_id", null);
});

const buildVarsFromSelectedContract = () => {
  const uuid = form.values.contract_uuid;
  if (!uuid) return {};
  const c = (contractsForCase.value || []).find((x) => x.uuid === uuid);
  if (!c) return {};
  const vars = {
    contract: {
      uuid: c.uuid,
      reference: c.reference,
      start_date: c.start_date || "",
      end_date: c.end_date || "",
    },
  };
  if (c.account) {
    vars.account = {
      reference: c.account.reference,
      type: c.account.type,
      initial_amount:
        c.account.initial_amount ??
        (c.account.initial_amount_raw ? formatEu(c.account.initial_amount_raw) : null),
      balance_amount:
        c.account.balance_amount ??
        (c.account.balance_amount_raw ? formatEu(c.account.balance_amount_raw) : null),
      initial_amount_raw: c.account.initial_amount_raw ?? null,
      balance_amount_raw: c.account.balance_amount_raw ?? null,
    };
  }
  return vars;
};

const updateSmsFromSelection = async () => {
  if (!form.values.template_id) return;
  try {
    const url = route("clientCase.sms.preview", {
      client_case: props.clientCaseUuid,
    });
    const { data } = await axios.post(url, {
      template_id: form.values.template_id,
      contract_uuid: form.values.contract_uuid || null,
    });
    if (typeof data?.content === "string" && data.content.trim() !== "") {
      form.setFieldValue("message", data.content);
      return;
    }
  } catch (e) {
    // ignore and fallback
  }

  // Fallback to client-side template rendering
  const tpl = (pageSmsTemplates.value || []).find(
    (t) => t.id === form.values.template_id
  );
  if (tpl && typeof tpl.content === "string") {
    form.setFieldValue(
      "message",
      renderTokens(tpl.content, buildVarsFromSelectedContract())
    );
  }
};

watch(
  () => form.values.template_id,
  () => {
    if (!form.values.template_id) return;
    updateSmsFromSelection();
  }
);

watch(
  () => form.values.contract_uuid,
  () => {
    if (!form.values.template_id) return;
    updateSmsFromSelection();
  }
);

watch(pageSmsTemplates, (list) => {
  if (!Array.isArray(list)) return;
  if (!form.values.template_id && list.length > 0) {
    form.setFieldValue("template_id", list[0].id);
  }
});

const loadContractsForCase = async () => {
  try {
    const url = route("clientCase.contracts.list", {
      client_case: props.clientCaseUuid,
    });
    const res = await fetch(url, {
      headers: { "X-Requested-With": "XMLHttpRequest" },
      credentials: "same-origin",
    });
    const json = await res.json();
    contractsForCase.value = Array.isArray(json?.data) ? json.data : [];
  } catch (e) {
    contractsForCase.value = [];
  }
};

watch(
  () => props.show,
  (newVal) => {
    if (newVal) {
      form.resetForm({
        values: {
          message: "",
          template_id: pageSmsTemplates.value?.[0]?.id ?? null,
          contract_uuid: null,
          profile_id: pageSmsProfiles.value?.[0]?.id ?? null,
          sender_id: null,
          delivery_report: false,
        },
      });

      // Set default sender after profile is set
      const profileId = pageSmsProfiles.value?.[0]?.id;
      if (profileId) {
        const prof = (pageSmsProfiles.value || []).find((p) => p.id === profileId);
        if (prof?.default_sender_id) {
          const inList = sendersForSelectedProfile.value.find(
            (s) => s.id === prof.default_sender_id
          );
          if (inList) {
            form.setFieldValue("sender_id", prof.default_sender_id);
          }
        }
      }

      loadContractsForCase();
    }
  }
);

const closeSmsDialog = () => {
  emit("close");
};

const onSubmit = form.handleSubmit((values) => {
  if (!props.phone || !props.clientCaseUuid) return;

  processing.value = true;
  router.post(
    route("clientCase.phone.sms", {
      client_case: props.clientCaseUuid,
      phone_id: props.phone.id,
    }),
    values,
    {
      preserveScroll: true,
      onSuccess: () => {
        processing.value = false;
        closeSmsDialog();
      },
      onError: () => {
        processing.value = false;
      },
      onFinish: () => {
        processing.value = false;
      },
    }
  );
});

const open = computed({
  get: () => props.show,
  set: (value) => {
    if (!value) closeSmsDialog();
  },
});
</script>

<template>
  <Dialog v-model:open="open">
    <DialogContent class="sm:max-w-2xl">
      <DialogHeader>
        <DialogTitle>Pošlji SMS</DialogTitle>
        <DialogDescription>
          <p class="text-sm text-gray-600">
            Prejemnik: <span class="font-mono">{{ phone?.nu }}</span>
            <span v-if="phone?.country_code" class="ml-2 text-xs text-gray-500">
              CC +{{ phone.country_code }}
            </span>
          </p>
        </DialogDescription>
      </DialogHeader>

      <form @submit.prevent="onSubmit" class="space-y-4">
        <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
          <FormField v-slot="{ value, handleChange }" name="profile_id">
            <FormItem>
              <FormLabel>Profil</FormLabel>
              <Select :model-value="value" @update:model-value="handleChange">
                <FormControl>
                  <SelectTrigger>
                    <SelectValue placeholder="—" />
                  </SelectTrigger>
                </FormControl>
                <SelectContent>
                  <SelectItem :value="null">—</SelectItem>
                  <SelectItem v-for="p in pageSmsProfiles" :key="p.id" :value="p.id">
                    {{ p.name || "Profil #" + p.id }}
                  </SelectItem>
                </SelectContent>
              </Select>
              <FormMessage />
            </FormItem>
          </FormField>

          <FormField v-slot="{ value, handleChange }" name="sender_id">
            <FormItem>
              <FormLabel>Pošiljatelj</FormLabel>
              <Select :model-value="value" @update:model-value="handleChange">
                <FormControl>
                  <SelectTrigger>
                    <SelectValue placeholder="—" />
                  </SelectTrigger>
                </FormControl>
                <SelectContent>
                  <SelectItem :value="null">—</SelectItem>
                  <SelectItem
                    v-for="s in sendersForSelectedProfile"
                    :key="s.id"
                    :value="s.id"
                  >
                    {{ s.name || s.phone || "Sender #" + s.id }}
                  </SelectItem>
                </SelectContent>
              </Select>
              <FormMessage />
            </FormItem>
          </FormField>
        </div>

        <FormField v-slot="{ value, handleChange }" name="contract_uuid">
          <FormItem>
            <FormLabel>Pogodba</FormLabel>
            <Select :model-value="value" @update:model-value="handleChange">
              <FormControl>
                <SelectTrigger>
                  <SelectValue placeholder="—" />
                </SelectTrigger>
              </FormControl>
              <SelectContent>
                <SelectItem :value="null">—</SelectItem>
                <SelectItem v-for="c in contractsForCase" :key="c.uuid" :value="c.uuid">
                  {{ c.reference || c.uuid }}
                </SelectItem>
              </SelectContent>
            </Select>
            <p class="mt-1 text-xs text-gray-500">
              Uporabi podatke pogodbe (in računa) za zapolnitev {contract.*} in
              {account.*} mest.
            </p>
            <FormMessage />
          </FormItem>
        </FormField>

        <FormField v-slot="{ value, handleChange }" name="template_id">
          <FormItem>
            <FormLabel>Predloga</FormLabel>
            <Select :model-value="value" @update:model-value="handleChange">
              <FormControl>
                <SelectTrigger>
                  <SelectValue placeholder="—" />
                </SelectTrigger>
              </FormControl>
              <SelectContent>
                <SelectItem :value="null">—</SelectItem>
                <SelectItem v-for="t in pageSmsTemplates" :key="t.id" :value="t.id">
                  {{ t.name || "Predloga #" + t.id }}
                </SelectItem>
              </SelectContent>
            </Select>
            <FormMessage />
          </FormItem>
        </FormField>

        <FormField v-slot="{ componentField }" name="message">
          <FormItem>
            <FormLabel>Vsebina sporočila</FormLabel>
            <FormControl>
              <Textarea
                rows="4"
                placeholder="Vpišite SMS vsebino..."
                v-bind="componentField"
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        </FormField>

        <!-- Live counters -->
        <div class="text-xs text-gray-600 flex flex-col gap-1">
          <div>
            <span class="font-medium">Znakov:</span>
            <span class="font-mono">{{ charCount }}</span>
            <span class="mx-2">|</span>
            <span class="font-medium">Kodiranje:</span>
            <span>{{ smsEncoding }}</span>
            <span class="mx-2">|</span>
            <span class="font-medium">Deli SMS:</span>
            <span class="font-mono">{{ segments }}</span>
            <span class="mx-2">|</span>
            <span class="font-medium">Krediti:</span>
            <span class="font-mono">{{ creditsNeeded }}</span>
          </div>
          <div>
            <span class="font-medium">Omejitev:</span>
            <span class="font-mono">{{ maxAllowed }}</span>
            <span class="mx-2">|</span>
            <span class="font-medium">Preostanek:</span>
            <span class="font-mono" :class="{ 'text-red-600': remaining === 0 }">
              {{ remaining }}
            </span>
          </div>
          <p class="text-[11px] text-gray-500 leading-snug">
            Dolžina 160 znakov velja samo pri pošiljanju sporočil, ki vsebujejo znake, ki
            ne zahtevajo enkodiranja. Če npr. želite pošiljati šumnike, ki niso del
            7-bitne abecede GSM, morate uporabiti Unicode enkodiranje (UCS‑2). V tem
            primeru je največja dolžina enega SMS sporočila 70 znakov (pri daljših
            sporočilih 67 znakov na del), medtem ko je pri GSM‑7 160 znakov (pri daljših
            sporočilih 153 znakov na del). Razširjeni znaki (^{{ "{" }}}}\\[]~| in €)
            štejejo dvojno. Največja dovoljena dolžina po ponudniku: 640 (GSM‑7) oziroma
            320 (UCS‑2) znakov.
          </p>
        </div>

        <FormField v-slot="{ value, handleChange }" name="delivery_report">
          <FormItem class="flex flex-row items-start space-x-3 space-y-0">
            <FormControl>
              <Switch :model-value="value" @update:model-value="handleChange" />
            </FormControl>
            <div class="space-y-1 leading-none">
              <FormLabel>Zahtevaj poročilo o dostavi</FormLabel>
            </div>
          </FormItem>
        </FormField>
      </form>

      <DialogFooter>
        <Button variant="outline" @click="closeSmsDialog" :disabled="processing">
          Prekliči
        </Button>
        <Button @click="onSubmit" :disabled="processing || !form.values.message">
          Pošlji
        </Button>
      </DialogFooter>
    </DialogContent>
  </Dialog>
</template>
