<script setup>
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import AppIcon from './AppIcon.vue';
import { boot } from '../format';

/**
 * Add / edit sheet. One form serves both: passing an expense turns it into an
 * edit, and the field errors coming back from the API are shown in place.
 */
const props = defineProps({
    open: { type: Boolean, default: false },
    expense: { type: Object, default: null },
    categories: { type: Array, default: () => [] },
    saving: { type: Boolean, default: false },
    errors: { type: Object, default: () => ({}) },
});

const emit = defineEmits(['close', 'submit']);

const blank = () => ({
    description: '',
    category: '',
    amount: '',
    payment_method: 'Cash',
    expense_date: '',
    remark: '',
});

const form = ref(blank());
const descriptionInput = ref(null);
const amountInput = ref(null);

/** The em dash the server uses for "no category" is not a category name. */
const categoryOf = (expense) => (expense.category === '—' ? '' : expense.category);

watch(() => props.open, async (open) => {
    document.body.style.overflow = open ? 'hidden' : '';
    if (!open) return;

    form.value = props.expense
        ? {
            description: props.expense.description ?? '',
            category: categoryOf(props.expense),
            amount: String(props.expense.amount ?? ''),
            payment_method: props.expense.payment_method ?? 'Cash',
            expense_date: props.expense.expense_date ?? '',
            remark: props.expense.remark ?? '',
        }
        : blank();

    await nextTick();
    // Editing usually means correcting the amount; adding starts at the top.
    (props.expense ? amountInput.value : descriptionInput.value)?.focus();
});

function onKeydown(event) {
    if (props.open && event.key === 'Escape' && !props.saving) emit('close');
}

onMounted(() => document.addEventListener('keydown', onKeydown));
onBeforeUnmount(() => {
    document.removeEventListener('keydown', onKeydown);
    document.body.style.overflow = '';
});

const error = (field) => props.errors[field]?.[0];

function submit() {
    emit('submit', {
        description: form.value.description.trim(),
        category: form.value.category.trim(),
        amount: form.value.amount,
        payment_method: form.value.payment_method,
        expense_date: form.value.expense_date || null,
        remark: form.value.remark.trim() || null,
    });
}
</script>

<template>
    <div class="modal no-print" :class="{ 'is-open': open }" role="dialog" aria-modal="true"
         aria-labelledby="modal-title" @mousedown.self="saving || emit('close')">
        <div class="modal-box">
            <form @submit.prevent="submit">
                <div class="modal-head">
                    <span class="head-icon"><AppIcon name="receipt" :size="18"/></span>
                    <h2 id="modal-title">{{ expense ? 'খরচ এডিট করুন' : 'নতুন খরচ যোগ করুন' }}</h2>
                    <button type="button" class="modal-close" aria-label="বন্ধ করুন" @click="emit('close')">
                        <AppIcon name="x" :size="17"/>
                    </button>
                </div>

                <div class="modal-body">
                    <div class="field span-2" :class="{ 'has-error': error('description') }">
                        <label for="i-description">{{ boot.labels.description }} <span class="req">*</span></label>
                        <input id="i-description" ref="descriptionInput" v-model="form.description" type="text"
                               required maxlength="255" placeholder="যেমন: বোরখা">
                        <span v-if="error('description')" class="error">{{ error('description') }}</span>
                    </div>

                    <div class="field" :class="{ 'has-error': error('category') }">
                        <label for="i-category">{{ boot.labels.category }} <span class="req">*</span></label>
                        <input id="i-category" v-model="form.category" type="text" required maxlength="100"
                               list="category-list" placeholder="বাছুন বা নতুন লিখুন" autocomplete="off">
                        <datalist id="category-list">
                            <option v-for="category in categories" :key="category.id" :value="category.name"></option>
                        </datalist>
                        <span v-if="error('category')" class="error">{{ error('category') }}</span>
                    </div>

                    <div class="field" :class="{ 'has-error': error('amount') }">
                        <label for="i-amount">{{ boot.labels.amount }} <span class="req">*</span></label>
                        <input id="i-amount" ref="amountInput" v-model="form.amount" type="number" required
                               step="0.01" min="0" inputmode="decimal" placeholder="0">
                        <span v-if="error('amount')" class="error">{{ error('amount') }}</span>
                    </div>

                    <div class="field" :class="{ 'has-error': error('payment_method') }">
                        <label for="i-payment">{{ boot.labels.payment_method }}</label>
                        <select id="i-payment" v-model="form.payment_method" required>
                            <option v-for="method in boot.payment_methods" :key="method" :value="method">
                                {{ method }}
                            </option>
                        </select>
                        <span v-if="error('payment_method')" class="error">{{ error('payment_method') }}</span>
                    </div>

                    <div class="field" :class="{ 'has-error': error('expense_date') }">
                        <label for="i-date">{{ boot.labels.date }} <span class="hint">(ঐচ্ছিক)</span></label>
                        <input id="i-date" v-model="form.expense_date" type="date">
                        <span v-if="error('expense_date')" class="error">{{ error('expense_date') }}</span>
                    </div>

                    <div class="field span-2" :class="{ 'has-error': error('remark') }">
                        <label for="i-remark">{{ boot.labels.remark }} <span class="hint">(যেমন: 100+400+60)</span></label>
                        <input id="i-remark" v-model="form.remark" type="text" maxlength="255"
                               placeholder="হিসাবের ভাঙতি বা নোট">
                        <span v-if="error('remark')" class="error">{{ error('remark') }}</span>
                    </div>
                </div>

                <div class="modal-foot">
                    <button type="button" class="btn" :disabled="saving" @click="emit('close')">বাতিল</button>
                    <span class="spacer"></span>
                    <button type="submit" class="btn btn-primary" :disabled="saving">
                        <AppIcon :name="saving ? 'rotate' : 'check'" :size="16" :class="{ 'is-spinning': saving }"/>
                        <span>
                            {{ saving ? 'সংরক্ষণ হচ্ছে…' : (expense ? 'আপডেট করুন' : 'সংরক্ষণ করুন') }}
                        </span>
                    </button>
                </div>
            </form>
        </div>
    </div>
</template>
