<template>
<div class="container-xxl flex-grow-1 container-p-y">
    <div class="card shadow-sm rounded-lg p-6 max-w-2xl mx-auto">
    <h3 class="text-2xl font-semibold mb-3 text-center">마이 페이지</h3>
    <form @submit.prevent="handleSubmit">
        <div class="text-center">
        <label
            for="profilePic"
            class="rounded-circle m-auto ui-bg-cover position-relative cursor-pointer"
            id="profileLabel"
            :style="profilePreviewStyle"
        ></label>
        <input type="file" id="profilePic" class="d-none" @change="profileUpload" />
        <span v-if="profilerr" class="invalid-feedback d-block">{{ profilerr }}</span>
        </div>

        <div class="col-xl-12">
            <div class="d-flex">
            <div class="w-50 me-2">
                <UserFormInput
                title="입사일"
                name="entryDate"
                type="date"
                :value="form.entryDate"
                @update:data="form.entryDate = $event"
                />
            </div>

            <div class="d-flex flex-column w-50">
                <FormSelect
                title="컬러"
                name="color"
                :is-row="false"
                :is-label="true"
                :is-common="true"
                :is-color="true"
                :data="colorList"
                :value="form.color"
                @update:data="handleColorUpdate"
                />
                <span v-if="colorDuplicated" class="text-danger invalid-feedback mt-1 d-block">
                이미 사용 중인 컬러입니다.
                </span>
            </div>
            </div>

        <div class="d-flex">
            <UserFormInput title="생년월일" name="birth" type="date"
            :value="form.birth" @update:data="form.birth = $event" class="me-2 w-50" />
            <FormSelect title="MBTI" name="mbti" :is-row="false" :is-label="true"
            :is-common="true" :is-mbti="true" :data="mbtiList"
            :value="form.mbti" @update:data="form.mbti = $event" class="w-50" />
        </div>

        <ArrInput title="주소" name="address" v-model="form.address" :disabled="true" />

        <UserFormInput title="전화번호" name="phone" :value="form.phone"
            @update:data="form.phone = $event" @blur="checkPhoneDuplicateAndFormat"
            :maxlength="11" @keypress="onlyNumber" />
        <span v-if="phoneFormatError" class="text-danger invalid-feedback mt-1 d-block">
            전화번호 형식이 올바르지 않습니다.
        </span>
        <span v-if="phoneDuplicated" class="text-danger invalid-feedback mt-1 d-block">
            이미 사용 중인 전화번호입니다.
        </span>

        <!-- 기존 비밀번호 입력 -->
        <UserFormInput title="기존 비밀번호" name="currentPw" type="password"
            :value="password.current" @update:data="password.current = $event"
            @blur="checkCurrentPassword" @keypress="noSpace" />
        <span v-if="passwordError" class="text-danger invalid-feedback mt-1 d-block">
            비밀번호가 일치하지 않습니다.
        </span>

        <!-- 비밀번호 재설정 -->
        <div v-if="showResetPw">
            <UserFormInput title="새 비밀번호" name="newPw" type="password"
            :value="password.new" @update:data="password.new = $event" @keypress="noSpace" />
            <span v-if="password.new && password.new.length < 4"
            class="text-danger invalid-feedback mt-1 d-block">
            새 비밀번호는 최소 4자리 이상이어야 합니다.
            </span>
            <span v-if="password.new === password.current"
            class="text-danger invalid-feedback mt-1 d-block">
            기존 비밀번호와 다르게 설정해주세요.
            </span>

            <UserFormInput title="비밀번호 확인" name="confirmPw" type="password"
            :value="password.confirm" @update:data="password.confirm = $event" @keypress="noSpace" />
            <span v-if="password.confirm && password.confirm !== password.new"
            class="text-danger invalid-feedback mt-1 d-block">
            새 비밀번호와 일치하지 않습니다.
            </span>

            <div class="d-flex justify-content-end mt-2">
            <button type="button" class="btn btn-sm btn-outline-primary"
                :disabled="!canResetPassword"
                @click="handlePasswordReset">
                비밀번호 변경
            </button>
            </div>
        </div>

        <div class="d-flex mt-5">
            <button type="submit" class="btn btn-primary w-100"
            :disabled="!isChanged || phoneDuplicated || phoneFormatError   || colorDuplicated">
            정보 수정
            </button>
        </div>
        </div>
    </form>
    </div>
</div>
</template>

<script setup>
import { ref, computed, onMounted, watch} from 'vue';
import $api from '@api';
import UserFormInput from '@c/input/UserFormInput.vue';
import FormSelect from '@c/input/FormSelect.vue';
import ArrInput from '@c/input/ArrInput.vue';
import { useToastStore } from '@s/toastStore';

const toastStore = useToastStore();

const noSpace = (e) => {
    if (e.key === ' ') e.preventDefault();
};

const form = ref({
entryDate: '', birth: '', phone: '', color: '', mbti: '',
address: { address: '', detailAddress: '', postcode: '' },
id: ''
});
const originalData = ref({});
const profile = ref('');
const uploadedFile = ref(null);
const profileChanged = ref(false);
const profilerr = ref('');
const currentBlobUrl = ref('');
const colorDuplicated = ref(false);
const phoneDuplicated = ref(false);
const mbtiList = ref([]);
const colorList = ref([]);

const password = ref({ current: '', new: '', confirm: '' });
const passwordError = ref(false);
const phoneFormatError = ref(false);
const showResetPw = ref(false);

const canResetPassword = computed(() => {
return (
    password.value.new.length >= 4 &&
    password.value.new !== password.value.current &&
    password.value.new === password.value.confirm
);
});

watch(
    () => form.value.address.detailAddress,
    (newVal) => {
        if (newVal !== newVal.trim()) {
        form.value.address.detailAddress = newVal.trim();
        }
    }
);

const isChanged = computed(() => {
    const f = form.value;
    const o = originalData.value;
    return (
        f.entryDate !== o.entryDate || f.birth !== o.birth || f.phone !== o.phone ||
        f.color !== o.color || f.mbti !== o.mbti || profileChanged.value ||
        f.address.address !== o.address.address ||
        f.address.detailAddress !== o.address.detailAddress ||
        f.address.postcode !== o.address.postcode
    );
});

const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
const defaultProfile = "/img/icons/icon.png";
const getProfileImageUrl = (profilePath) =>
    profilePath && profilePath.trim() ? `${baseUrl}upload/img/profile/${profilePath}` : defaultProfile;
const profilePreviewStyle = computed(() => ({
    width: '100px',
    height: '100px',
    backgroundImage: `url(${profile.value})`,
    backgroundRepeat: 'no-repeat',
    backgroundSize: 'cover',
    backgroundPosition: 'center'
}));

const profileUpload = (e) => {
    const file = e.target.files[0];
    if (!file) return;
    if (file.size > 5 * 1024 * 1024 || !['image/jpeg', 'image/png'].includes(file.type)) {
        profilerr.value = '5MB 이하의 JPG/PNG 파일만 업로드 가능합니다.';
        return;
    }
    profilerr.value = '';
    if (currentBlobUrl.value) URL.revokeObjectURL(currentBlobUrl.value);
    uploadedFile.value = file;
    const newBlobUrl = URL.createObjectURL(file);
    profile.value = newBlobUrl;
    currentBlobUrl.value = newBlobUrl;
    profileChanged.value = true;
};

const onlyNumber = (e) => {
    if (!/[0-9]/.test(e.key)) e.preventDefault();
};

const checkPhoneDuplicateAndFormat = async () => {
    const currentPhone = form.value.phone.trim();

    // 형식 검사 (010으로 시작 + 숫자 8자리)
    const phoneRegex = /^010\d{8}$/;
    const isFormatValid = phoneRegex.test(currentPhone);

    phoneFormatError.value = !isFormatValid;

    // 중복 체크는 형식이 맞을 때만 수행
    if (isFormatValid) {
        const response = await $api.get('/user/checkPhone', {
        params: { memberTel: currentPhone },
        });

        // true면 사용 가능하다는 의미니까 → 중복 아님
        // false면 중복된 번호라는 의미니까 → 중복됨
        phoneDuplicated.value = currentPhone !== originalData.value.phone && !response.data.data;
    } else {
        // 형식이 맞지 않으면 중복 여부는 무시 (false로 초기화)
        phoneDuplicated.value = false;
    }
};

const handleColorUpdate = async (colorVal) => {
    form.value.color = colorVal;
    colorDuplicated.value = colorVal !== originalData.value.color &&
        (await $api.get('/user/checkColor', { params: { memberCol: colorVal } })).data.data;
};

const checkCurrentPassword = async () => {
    if (!password.value.current) return;
        const res = await $api.post('/user/checkPassword', {
            id: form.value.id,
            password: password.value.current
        });
    passwordError.value = res.data.data;
    showResetPw.value = !res.data.data;
};
const handlePasswordReset = async () => {
    const res = await $api.patch('/user/pwNew', {
        id: form.value.id,
        password: password.value.new
    });
    if (res.data.data) {
        toastStore.onToast('비밀번호가 변경되었습니다.', 's');
        password.value = { current: '', new: '', confirm: '' };
        showResetPw.value = false;
        passwordError.value = false;
    } else {
        toastStore.onToast('비밀번호 변경 실패', 'e');
    }
};

const formatDate = (isoDate) => isoDate?.split('T')[0] || '';

const loadInitialData = async () => {
    const user = (await $api.get('/user/userInfo')).data.data;
    const serverColors = (await $api.get('/user/color', { params: { type: 'YON' } })).data.data.map(c => ({
        value: c.CMNCODVAL, label: c.CMNCODNAM
}));
const matchedColor = serverColors.find(c => c.label === user.usercolor);
const colorCode = matchedColor ? matchedColor.value : user.color;
colorList.value = serverColors.some(c => c.value === colorCode)
    ? serverColors
    : [{ value: colorCode, label: user.usercolor }, ...serverColors];

const initData = {
    id: user.loginId,
    entryDate: formatDate(user.isCdt),
    birth: formatDate(user.birth),
    phone: user.phone || '',
    color: colorCode,
    mbti: user.mbit || '',
    address: {
    address: user.address || '',
    detailAddress: user.addressDetail || '',
    postcode: user.zipcode || ''
    }
};
form.value = { ...initData };
originalData.value = { ...initData };
profile.value = getProfileImageUrl(user.profile);
profileChanged.value = false;

const mbtiRes = await $api.get('/user/mbti');
    mbtiList.value = mbtiRes.data.data.map(m => ({ value: m.CMNCODVAL, label: m.CMNCODNAM }));
};

const handleSubmit = async () => {
    const formData = new FormData();
    Object.entries(form.value).forEach(([k, v]) => {
        if (typeof v === 'object') {
            formData.append('address', v.address);
            formData.append('detailAddress', v.detailAddress);
            formData.append('postcode', v.postcode);
        } else {
        formData.append(k, v);
        }
    });
    if (uploadedFile.value) formData.append('profileFile', uploadedFile.value);

    if (form.value.color !== originalData.value.color) {
        if (form.value.color) await $api.patch('/user/updateColorYon', { color: form.value.color, type: 'YON' });
        if (originalData.value.color) await $api.patch('/user/updateColorChange', { color: originalData.value.color, type: 'YON' });
    }

    await $api.patch('/user/updateInfo', formData, { isFormData: true });
    originalData.value = { ...form.value };
    profileChanged.value = false;
    location.reload();
    toastStore.onToast('정보가 수정되었습니다.', 's');
};

onMounted(() => loadInitialData());
</script>

<style scoped>
</style>
