<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { ExternalAuthControllerService } from "@/components/service/management/ExternalAuthControllerService";
import {
  AddFileParamsSwagger,
  AddMinioParamsSwagger,
  EdgePkgInfoVOModel,
} from "@/components/models/management/ExternalAuthController";

type PackageOption = { label: string; value: string; raw: any };

type MinioRegisterModel = EdgePkgInfoVOModel & {
  objectName: string;
  type: "type1" | "type2";
  localPath: string;
};

const props = defineProps<{
  packages: PackageOption[];
  packagesLoading?: boolean;
  packagesError?: string;
  artifactPath?: string;
  token: string;
  hideArtifactPath?: boolean;
  hideUploadFile?: boolean;
}>();

const emit = defineEmits<{
  (e: "close-modal"): void;
  (e: "handle-data", value: any): void;
}>();

/* ========================= 폼/상태 ========================= */
const form = ref({
  package_id: "",
  sw_id: "",
  sw_version: "",
  software_name: "",
  executed: true,
  file_type: "bundle" as "bundle" | "single",
  os: "" as "" | "Windows" | "Linux",

  win_exe_name: "",
  win_root_path: "",
  linux_exe_name: "",
  linux_root_path: "",

  install_location: "",
  private_only: false,
});

const saving = ref(false);
const errorMsg = ref("");
const successDialog = ref(false);
const pendingPayload = ref<any>(null);

/* ========================= 파일 업로드 ========================= */
const file = ref<File | null>(null);
const fileInput = ref<HTMLInputElement | null>(null);
const onFileChange = (e: Event) => {
  const input = e.target as HTMLInputElement;
  file.value = input.files?.[0] ?? null;
};
const clearFile = () => {
  if (fileInput.value) fileInput.value.value = "";
  file.value = null;
};

/* ========================= SW/EDGE 선택 + 목록 조회 ========================= */
const sourceType = ref<"" | "sw" | "edge">(""); // SW or EDGE

const remotePackages = ref<PackageOption[]>([]);
const remoteLoading = ref(false);
const remoteError = ref("");

const pkgOptions = computed<PackageOption[]>(() =>
  remotePackages.value.length ? remotePackages.value : (props.packages ?? []),
);
/* ========================= 표시/숨김 스위치 ========================= */
const showArtifactPath = computed(() => !!props.artifactPath);
const showUploadFile = computed(() => !showArtifactPath.value);

async function fetchPackages() {
  remoteError.value = "";
  remotePackages.value = [];
  form.value.package_id = "";

  if (!sourceType.value) {
    remoteError.value = "SW 또는 EDGE를 먼저 선택하세요.";
    return;
  }
  if (!props.token) {
    remoteError.value = "토큰이 없습니다. 다시 로그인하세요.";
    return;
  }

  let id: string;
  try {
    id = getRequiredExternalAuthId(); // ✅ 반드시 external-auth.id
  } catch (e: any) {
    remoteError.value = e?.message || "external-auth의 id가 필요합니다.";
    return;
  }
  try {
    remoteLoading.value = true;

    const res =
      sourceType.value === "edge"
        ? await ExternalAuthControllerService.edgeSearch(id, props.token)
        : await ExternalAuthControllerService.swSearch(id, props.token);

    // ✅ 응답을 안전하게 펼쳐서 배열을 추출
    const payload = (res as any)?.data ?? res; // 1차
    const maybeList =
      (Array.isArray(payload?.data) ? payload?.data : null) ??
      (Array.isArray(payload?.list) ? payload?.list : null) ??
      (Array.isArray(payload) ? payload : null);
    const list: any[] = Array.isArray(maybeList)
      ? maybeList
      : Array.isArray((payload?.data as any)?.data) // 2차 중첩 (data.data)
        ? (payload.data as any).data
        : [];

    remotePackages.value = list.map((it: any) => {
      // value는 ed_pkg_serial(또는 동의어) 우선
      const val = String(
        it?.ed_pkg_serial ??
          it?.edPkgSerial ??
          it?.package_id ??
          it?.id ??
          it?.pkg_id ??
          it?.value ??
          "",
      );

      // label은 package_name > pkg_name > sw_name > name 우선
      const name =
        it?.package_name ??
        it?.pkg_name ??
        it?.sw_name ??
        it?.name ??
        "unknown";

      return {
        label: `${name}`,
        value: val,
        raw: it,
      };
    });

    if (!remotePackages.value.length) {
      remoteError.value = "해당 대상의 패키지 목록이 없습니다.";
    }
  } catch (e: any) {
    remoteError.value =
      e?.response?.data?.message ||
      e?.message ||
      "목록 조회 중 오류가 발생했습니다.";
  } finally {
    remoteLoading.value = false;
  }
}

// 라디오가 바뀌면 자동 조회 + 필드 초기화
watch(sourceType, async (v) => {
  remotePackages.value = [];
  form.value.package_id = "";
  form.value.win_exe_name = "";
  form.value.win_root_path = "";
  form.value.linux_exe_name = "";
  form.value.linux_root_path = "";
  form.value.os = "";
  if (v) await fetchPackages();
});

/* ========================= 선택 패키지 → 읽기전용/OS ========================= */
const selectedOption = computed(() =>
  pkgOptions.value?.find((p) => p.value === form.value.package_id),
);
const selectedRaw = computed(() => selectedOption.value?.raw ?? null);

const readonlyFields = computed(() => ({
  swTypeName: selectedRaw.value?.sw_type_name ?? "",
  swGroupName: selectedRaw.value?.sw_group_name ?? "",
  manufacturer: selectedRaw.value?.sw_manufacturer ?? "",
  packageId: selectedRaw.value?.package_id ?? "",
  packageName: selectedRaw.value?.package_name ?? "",
}));

function onPickPackage() {
  form.value.win_exe_name = selectedRaw.value?.window_exe_name ?? "";
  form.value.win_root_path = selectedRaw.value?.window_root_location ?? "";
  form.value.linux_exe_name = selectedRaw.value?.linux_exe_name ?? "";
  form.value.linux_root_path = selectedRaw.value?.linux_root_location ?? "";

  if (form.value.win_exe_name || form.value.win_root_path)
    form.value.os = "Windows";
  else if (form.value.linux_exe_name || form.value.linux_root_path)
    form.value.os = "Linux";
}
function getRequiredExternalAuthId(): string {
  try {
    const raw = localStorage.getItem("external-auth");
    const obj = raw ? JSON.parse(raw) : null;
    const id = obj?.id;
    if (id === undefined || id === null || String(id).trim() === "") {
      throw new Error(
        "external-auth의 id가 없습니다. 로그인 후 다시 시도하세요.",
      );
    }
    return String(id);
  } catch {
    throw new Error(
      "external-auth의 id를 읽을 수 없습니다. 로그인 후 다시 시도하세요.",
    );
  }
}
/* ========================= 기타 계산값 ========================= */
const isWin = computed(() => form.value.os === "Windows");
const isLinux = computed(() => form.value.os === "Linux");
const archiveTypeCode = computed(() =>
  form.value.file_type === "bundle" ? 1 : 0,
);
const swTypeCode = computed(() => (sourceType.value === "edge" ? 1 : 0));

const toInt = (v: unknown, fallback = 1) => {
  const n = parseInt(String(v ?? "").trim(), 10);
  return Number.isFinite(n) ? n : fallback;
};
const minioType = ref<"type1" | "type2">("type2");

async function submit() {
  errorMsg.value = "";
  if (!sourceType.value) return (errorMsg.value = "SW/EDGE를 선택하세요.");
  if (!form.value.sw_id?.trim())
    return (errorMsg.value = "SW ID를 입력하세요.");
  if (!form.value.software_name?.trim())
    return (errorMsg.value = "SW 명칭을 입력하세요.");
  if (!form.value.install_location?.trim())
    return (errorMsg.value = "설치 위치를 입력하세요.");
  if (!props.token) return (errorMsg.value = "토큰이 없습니다.");
  if (!selectedRaw.value) return (errorMsg.value = "패키지를 선택하세요.");
  let userId: string;
  try {
    userId = getRequiredExternalAuthId();
  } catch (e: any) {
    errorMsg.value = e?.message || "external-auth의 id가 필요합니다.";
    return;
  }
  const adSerial =
    selectedRaw.value?.ad_pkg_serial ?? selectedRaw.value?.adPkgSerial;
  const edSerial =
    selectedRaw.value?.ed_pkg_serial ?? selectedRaw.value?.edPkgSerial;
  const rawSerial = sourceType.value === "sw" ? adSerial : edSerial;
  const pkgSerial = Number.parseInt(String(rawSerial ?? "").trim(), 10);
  if (!Number.isFinite(pkgSerial))
    return (errorMsg.value = "패키지 시리얼이 없습니다.");
  const common: Omit<AddFileParamsSwagger, "pkg_serial"> & {
    pkg_serial: number;
  } = {
    sw_id: (form.value.sw_id || "").trim(),
    sw_version: parseFloat(String(form.value.sw_version)),
    sw_name: (form.value.software_name || "").trim(),
    authId: props.token,
    pkg_serial: pkgSerial,
    archiveType: form.value.file_type === "bundle" ? 1 : 0,
    execYn: form.value.executed ? 1 : 0,
    secretAt: !!form.value.private_only,
    downloadLocation: (form.value.install_location || "").trim(),
    user_id: userId,
    sw_type: sourceType.value === "edge" ? 1 : 0,
    creation_datetime: new Date().toISOString(),
  };
  if (props.hideArtifactPath) {
    // Upload 모드 → 파일 필수
    if (!file.value) return (errorMsg.value = "업로드 파일을 선택하세요.");
  }
  if (props.hideUploadFile) {
    // Artifact 모드 → artifactPath 필수, 그리고 파일은 무시
    if (file.value) clearFile();
    if (!props.artifactPath)
      return (errorMsg.value = "Artifact 경로가 없습니다.");
  }
  try {
    saving.value = true;
    let res: any;
    if (file.value) {
      const params: AddFileParamsSwagger = { ...common };
      res = await ExternalAuthControllerService.add(params, file.value);
    } else {
      const params: AddMinioParamsSwagger = {
        ...common,
        objectName: props.artifactPath || "",
        type: minioType.value,
        localPath: (form.value.install_location || "").trim(),
      };
      res = await ExternalAuthControllerService.addMinio(params);
    }

    const ok =
      res?.status === 200 ||
      res?.success === true ||
      res?.data?.success === true;
    if (!ok) {
      const msg =
        res?.data?.message ||
        res?.data?.errorMessage ||
        res?.errorMessage ||
        "등록에 실패했습니다.";
      throw new Error(msg);
    }

    pendingPayload.value = {
      ...form.value,
      artifact_path: props.artifactPath ?? "",
    };
    successDialog.value = true;
    clearFile();
  } catch (e: any) {
    errorMsg.value =
      e?.response?.data?.message ||
      e?.message ||
      "등록 중 오류가 발생했습니다.";
  } finally {
    saving.value = false;
  }
}

function confirmSuccess() {
  if (pendingPayload.value) emit("handle-data", pendingPayload.value);
  emit("close-modal");
  successDialog.value = false;
}

/* ========================= ESC 닫기 ========================= */
function onEsc(e: KeyboardEvent) {
  if (e.key === "Escape") emit("close-modal");
}
onMounted(() => window.addEventListener("keydown", onEsc));
onBeforeUnmount(() => window.removeEventListener("keydown", onEsc));
</script>

<template>
  <v-card rounded="lg" elevation="4" max-height="85vh" class="overflow-auto">
    <v-card-title
      class="text-white text-h6 font-weight-bold"
      style="background: #1976d2"
    >
      Vehicle Intelligence Software Registration
    </v-card-title>

    <v-defaults-provider
      :defaults="{
        VTextField: {
          density: 'compact',
          variant: 'outlined',
          hideDetails: true,
        },
        VSelect: { density: 'compact', variant: 'outlined', hideDetails: true },
        VRadioGroup: { density: 'compact' },
        VCheckbox: { density: 'compact' },
        VAlert: { density: 'compact' },
      }"
    >
      <!-- 1) 등록 대상 선택 -->
      <v-card-text class="pa-4">
        <v-row dense class="mb-2">
          <v-col cols="12" md="5">
            <div class="text-body-2 font-weight-medium mb-1">등록 대상</div>
            <v-radio-group v-model="sourceType" inline>
              <v-radio class="mr-8" label="Vehicle" value="sw" />
              <v-radio label="EDGE" value="edge" />
            </v-radio-group>
          </v-col>
        </v-row>

        <!-- 2) 패키지 (라디오 변경 시 자동 조회됨) -->
        <v-row dense class="mb-2">
          <v-col cols="12">
            <div class="text-body-2 font-weight-medium mb-1">패키지</div>
            <v-select
              v-model="form.package_id"
              :items="pkgOptions"
              item-title="label"
              item-value="value"
              :loading="remoteLoading || props.packagesLoading"
              :disabled="remoteLoading || !sourceType"
              :placeholder="
                sourceType
                  ? '패키지를 선택하세요.'
                  : '등록 대상을 먼저 선택하세요.'
              "
              @update:model-value="onPickPackage"
            />
          </v-col>
        </v-row>

        <!-- 자동 표기 -->
        <v-row dense class="mb-2">
          <v-col cols="12" md="6">
            <v-text-field
              label="SW 종류"
              :model-value="readonlyFields.swTypeName"
              disabled
            />
          </v-col>
          <v-col cols="12" md="6">
            <v-text-field
              label="SW 상세 종류"
              :model-value="readonlyFields.swGroupName"
              disabled
            />
          </v-col>
          <v-col cols="12" md="6">
            <v-text-field
              label="제조사"
              :model-value="readonlyFields.manufacturer"
              disabled
            />
          </v-col>
          <v-col cols="12" md="6">
            <v-text-field
              label="패키지 번호"
              :model-value="readonlyFields.packageId"
              disabled
            />
          </v-col>
        </v-row>
      </v-card-text>

      <v-divider class="mx-4" />

      <!-- 사용자 입력 -->
      <v-card-text class="pa-4 pt-3">
        <v-row dense class="mb-2">
          <v-col cols="12" md="6"
            ><v-text-field label="SW ID" v-model="form.sw_id"
          /></v-col>
          <v-col cols="12" md="6">
            <v-text-field
              label="SW 버전"
              v-model="form.sw_version"
              type="number"
              min="0"
              step="0.01"
              inputmode="decimal"
            />
          </v-col>
          <v-col cols="12"
            ><v-text-field
              label="SW 명칭 (Software Name)"
              v-model="form.software_name"
          /></v-col>
        </v-row>

        <v-row dense class="mb-1">
          <v-col cols="12" md="6">
            <v-radio-group v-model="form.executed" inline>
              <template #label
                ><span class="text-body-2">실행 여부</span></template
              >
              <v-radio class="mr-13" label="실행" :value="true" />
              <v-radio label="미실행" :value="false" />
            </v-radio-group>
          </v-col>
          <v-col cols="12" md="3">
            <v-radio-group v-model="form.file_type" inline>
              <template #label
                ><span class="text-body-2">파일 종류</span></template
              >
              <v-radio class="mr-13" label="묶음" value="bundle" />
              <v-radio label="단일" value="single" />
            </v-radio-group>
          </v-col>
        </v-row>

        <v-row dense class="mb-1">
          <v-col cols="12" md="6">
            <v-radio-group v-model="form.os" inline>
              <template #label><span class="text-body-2">OS</span></template>
              <v-radio class="mr-4" label="Windows" value="Windows" />
              <v-radio label="Linux" value="Linux" />
            </v-radio-group>
          </v-col>
        </v-row>

        <!-- Windows -->
        <v-row dense v-if="isWin" class="mb-1">
          <v-col cols="12"
            ><div class="text-body-2 font-weight-medium mb-1">
              Windows
            </div></v-col
          >
          <v-col cols="12" md="6"
            ><v-text-field
              label="윈도우 실행 파일명"
              v-model="form.win_exe_name"
              disabled
          /></v-col>
          <v-col cols="12" md="6"
            ><v-text-field
              label="윈도우 경로"
              v-model="form.win_root_path"
              disabled
          /></v-col>
        </v-row>

        <!-- Linux -->
        <v-row dense v-if="isLinux" class="mb-1">
          <v-col cols="12"
            ><div class="text-body-2 font-weight-medium mb-1">Linux</div></v-col
          >
          <v-col cols="12" md="6"
            ><v-text-field
              label="리눅스 실행 파일명"
              v-model="form.linux_exe_name"
              disabled
          /></v-col>
          <v-col cols="12" md="6"
            ><v-text-field
              label="리눅스 경로"
              v-model="form.linux_root_path"
              disabled
          /></v-col>
        </v-row>

        <!-- Artifact Path -->
        <v-row dense class="mb-1" v-if="!props.hideArtifactPath">
          <v-col cols="12">
            <v-text-field
              label="차량 SW 파일 (Artifact Path)"
              :model-value="props.artifactPath || '-'"
              disabled
            />
          </v-col>
        </v-row>

        <!-- 파일 업로드 -->
        <v-row dense class="mb-1" v-if="!props.hideUploadFile">
          <v-col cols="12">
            <div class="text-body-2 font-weight-medium mb-1">업로드 파일</div>
            <div class="d-flex align-center ga-3">
              <v-btn size="small" color="primary" @click="fileInput?.click()"
                >파일 선택</v-btn
              >
              <span v-if="file" class="text-body-2">
                {{ file.name }} ({{ file.size.toLocaleString() }} bytes)
              </span>
              <v-btn
                v-if="file"
                size="x-small"
                variant="text"
                class="ml-1"
                @click="clearFile"
                >지우기</v-btn
              >
            </div>
            <input
              ref="fileInput"
              type="file"
              class="d-none"
              @change="onFileChange"
            />
          </v-col>
        </v-row>

        <!-- 설치 위치 & 등록인만 접근 -->
        <v-row dense>
          <v-col cols="12" md="8"
            ><v-text-field label="설치 위치" v-model="form.install_location"
          /></v-col>
          <v-col cols="12" md="4" class="d-flex align-center">
            <v-checkbox
              v-model="form.private_only"
              label="등록인만 접근 여부"
              hide-details
            />
          </v-col>
        </v-row>

        <!-- 에러 메시지 -->
        <v-alert
          v-if="errorMsg"
          type="error"
          variant="tonal"
          class="mt-3"
          density="comfortable"
        >
          {{ errorMsg }}
        </v-alert>
      </v-card-text>

      <v-card-actions class="py-2 px-3">
        <v-spacer />
        <v-btn color="success" :loading="saving" @click="submit">SAVE</v-btn>
        <v-btn variant="text" :disabled="saving" @click="$emit('close-modal')"
          >CANCEL</v-btn
        >
      </v-card-actions>
    </v-defaults-provider>

    <v-dialog v-model="successDialog" width="360" persistent>
      <v-card rounded="lg">
        <v-card-title class="text-h6" style="background: #1976d2"
          >등록 완료</v-card-title
        >
        <v-card-text class="font-weight-bold text-center"
          >등록이 완료되었습니다.</v-card-text
        >
        <v-card-actions>
          <v-spacer />
          <v-btn color="primary" @click="confirmSuccess">확인</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </v-card>
</template>
