#!/bin/bash
# ============================================================
# SaaS Accounting — Paid To / Received From Party Field
# Adds party selector (Customer/Vendor/Employee/Other Name)
# to Cash Payment, Bank Payment, Cash Receipt, Bank Receipt
#
# Run: bash deploy_party_field.sh
# From: ~/public_html/saas-accounting/
# ============================================================
set -e
cd ~/public_html/saas-accounting

echo ""
echo "=============================================="
echo "  Party Field Deploy (Paid To / Received From)"
echo "=============================================="
echo ""

# ── 1. Add party_search AJAX endpoint to routes ───────────────────────────────
echo "Step 1: Adding party search route..."
python3 << 'PYEOF'
content = open('routes/web.php').read()
old = "    Route::prefix('accounting')->name('coa.')->group(function () {"
new = "    // Party search (unified: customers, vendors, employees, other names)\n    Route::get('/party/search', [\\App\\Http\\Controllers\\Company\\Accounting\\AccountingVouchersController::class, 'partySearch'])->name('party.search');\n\n    Route::prefix('accounting')->name('coa.')->group(function () {"
if 'party.search' not in content:
    content = content.replace(old, new)
    open('routes/web.php','w').write(content)
    print("  Route added.")
else:
    print("  Route already exists.")
PYEOF

# ── 2. Add partySearch method to AccountingVouchersController ─────────────────
echo "Step 2: Adding partySearch() and updating store/update..."
python3 << 'PYEOF'
content = open('app/Http/Controllers/Company/Accounting/AccountingVouchersController.php').read()

# Add partySearch method before formData
party_search_method = '''
    // ── Party Search (AJAX) ───────────────────────────────────────────────────
    public function partySearch(\\Illuminate\\Http\\Request $request)
    {
        $companyId = auth()->user()->company_id;
        $q         = trim($request->input('q', ''));
        $results   = [];

        $like = "%{$q}%";

        // Customers
        \\App\\Models\\Customer::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->whereNull('deleted_at')
            ->where('is_active', true)
            ->where(fn($x) => $x->where('name','like',$like)->orWhere('code','like',$like))
            ->orderBy('name')->limit(15)
            ->get(['id','name','code'])
            ->each(fn($r) => $results[] = [
                'id'   => 'customer_'.$r->id,
                'text' => ($r->code ? '['.$r->code.'] ' : '').$r->name,
                'type' => 'Customer',
                'party_id'   => $r->id,
                'party_type' => 'customer',
            ]);

        // Vendors
        \\App\\Models\\Vendor::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->whereNull('deleted_at')
            ->where('is_active', true)
            ->where(fn($x) => $x->where('name','like',$like)->orWhere('code','like',$like))
            ->orderBy('name')->limit(15)
            ->get(['id','name','code'])
            ->each(fn($r) => $results[] = [
                'id'   => 'vendor_'.$r->id,
                'text' => ($r->code ? '['.$r->code.'] ' : '').$r->name,
                'type' => 'Vendor',
                'party_id'   => $r->id,
                'party_type' => 'vendor',
            ]);

        // Employees
        \\App\\Models\\Employee::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->whereNull('deleted_at')
            ->where('is_active', true)
            ->where(fn($x) => $x->where('name','like',$like)->orWhere('code','like',$like))
            ->orderBy('name')->limit(10)
            ->get(['id','name','code'])
            ->each(fn($r) => $results[] = [
                'id'   => 'employee_'.$r->id,
                'text' => ($r->code ? '['.$r->code.'] ' : '').$r->name,
                'type' => 'Employee',
                'party_id'   => $r->id,
                'party_type' => 'employee',
            ]);

        // Other Names
        \\App\\Models\\OtherName::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->whereNull('deleted_at')
            ->where('is_active', true)
            ->where(fn($x) => $x->where('name','like',$like)->orWhere('code','like',$like))
            ->orderBy('name')->limit(10)
            ->get(['id','name','code'])
            ->each(fn($r) => $results[] = [
                'id'   => 'othername_'.$r->id,
                'text' => ($r->code ? '['.$r->code.'] ' : '').$r->name,
                'type' => 'Other Name',
                'party_id'   => $r->id,
                'party_type' => 'other_name',
            ]);

        return response()->json(['results' => $results]);
    }

'''

# Insert before formData()
target = '    private function formData'
if 'partySearch' not in content:
    content = content.replace(target, party_search_method + '    private function formData')
    print("  partySearch() added.")
else:
    print("  partySearch() already exists.")

# Add party_id and party_type to store validation
old_store_val = """        $request->validate([
            'voucher_date'       => 'required|date',
            'reference'          => 'nullable|string|max:100',
            'currency_id'        => 'nullable|integer|exists:currencies,id',
            'exchange_rate'      => 'nullable|numeric|min:0.000001',
            'narration'          => 'nullable|string|max:500',
            'lines'              => 'required|array|min:1',
            'lines.*.account_id' => 'required|integer|exists:accounts,id',
            'lines.*.dr_cr'      => 'required|in:dr,cr',
            'lines.*.amount'     => 'required|numeric|min:0.01',
            'lines.*.description'=> 'nullable|string|max:255',
            'lines.*.tax_code_id'=> 'nullable|integer|exists:tax_codes,id',
        ]);"""

new_store_val = """        $request->validate([
            'voucher_date'       => 'required|date',
            'reference'          => 'nullable|string|max:100',
            'party_type'         => 'nullable|string|in:customer,vendor,employee,other_name',
            'party_id'           => 'nullable|integer',
            'currency_id'        => 'nullable|integer|exists:currencies,id',
            'exchange_rate'      => 'nullable|numeric|min:0.000001',
            'narration'          => 'nullable|string|max:500',
            'lines'              => 'required|array|min:1',
            'lines.*.account_id' => 'required|integer|exists:accounts,id',
            'lines.*.dr_cr'      => 'nullable|in:dr,cr',
            'lines.*.amount'     => 'nullable|numeric|min:0',
            'lines.*.debit'      => 'nullable|numeric|min:0',
            'lines.*.credit'     => 'nullable|numeric|min:0',
            'lines.*.description'=> 'nullable|string|max:255',
            'lines.*.tax_code_id'=> 'nullable|integer|exists:tax_codes,id',
        ]);"""

content = content.replace(old_store_val, new_store_val, 1)

# Add party to voucher create array
old_create = """                'voucher_date'   => $request->voucher_date,
                'reference'      => $request->reference,
                'currency_id'    => $request->currency_id ?: null,
                'exchange_rate'  => $request->exchange_rate ?: 1,
                'narration'      => $request->narration,
                'status'         => 'draft',
                'created_by'     => auth()->id(),"""

new_create = """                'voucher_date'   => $request->voucher_date,
                'reference'      => $request->reference,
                'party_id'       => $request->party_id ?: null,
                'party_type'     => $request->party_type ?: null,
                'currency_id'    => $request->currency_id ?: null,
                'exchange_rate'  => $request->exchange_rate ?: 1,
                'narration'      => $request->narration,
                'status'         => 'draft',
                'created_by'     => auth()->id(),"""

content = content.replace(old_create, new_create, 1)

# Add party to update array
old_update = """            $voucher->update([
                'fiscal_year_id' => $fiscalYear?->id ?? $voucher->fiscal_year_id,
                'voucher_date'   => $request->voucher_date,
                'reference'      => $request->reference,
                'currency_id'    => $request->currency_id ?: null,
                'exchange_rate'  => $request->exchange_rate ?: 1,
                'narration'      => $request->narration,
                'status'         => 'draft', // Reset to draft on edit
            ]);"""

new_update = """            $voucher->update([
                'fiscal_year_id' => $fiscalYear?->id ?? $voucher->fiscal_year_id,
                'voucher_date'   => $request->voucher_date,
                'reference'      => $request->reference,
                'party_id'       => $request->party_id ?: null,
                'party_type'     => $request->party_type ?: null,
                'currency_id'    => $request->currency_id ?: null,
                'exchange_rate'  => $request->exchange_rate ?: 1,
                'narration'      => $request->narration,
                'status'         => 'draft',
            ]);"""

content = content.replace(old_update, new_update, 1)

open('app/Http/Controllers/Company/Accounting/AccountingVouchersController.php','w').write(content)
print("  Controller updated.")
PYEOF

# ── 3. Update voucher create.blade.php — add party field ──────────────────────
echo "Step 3: Updating voucher create view..."
python3 << 'PYEOF'
content = open('resources/views/accounting/vouchers/create.blade.php').read()

# Party field label
party_label_block = """
            {{-- Paid To / Received From (payment/receipt vouchers only) --}}
            @php
                $partyLabel = match($voucherType) {
                    'cash_payment','bank_payment' => 'Paid To',
                    'cash_receipt','bank_receipt' => 'Received From',
                    default => null,
                };
                $partyTypes = ['cash_payment','bank_payment','cash_receipt','bank_receipt'];
            @endphp
            @if(in_array($voucherType, $partyTypes))
            <div class="col-12 col-sm-6 col-md-3">
                <label class="form-label fw-semibold">{{ $partyLabel }}</label>
                {{-- Hidden fields to store resolved party_id and party_type --}}
                <input type="hidden" name="party_id"   id="partyId"   value="{{ old('party_id',   $voucher->party_id   ?? '') }}">
                <input type="hidden" name="party_type" id="partyType" value="{{ old('party_type', $voucher->party_type ?? '') }}">
                {{-- Select2 with AJAX search --}}
                <select id="partySelect" class="form-select" style="width:100%">
                    @if(isset($voucher) && $voucher->party_id && $voucher->party_type)
                        <option value="{{ $voucher->party_type.'_'.$voucher->party_id }}" selected>
                            {{ $voucher->party_type.'_'.$voucher->party_id }}
                        </option>
                    @endif
                </select>
            </div>
            @endif
"""

# Insert after the Narration field (before closing row div)
old_narration = """            {{-- Narration --}}
            <div class="col-12 col-md-4">
                <label class="form-label fw-semibold">Narration</label>
                <input type="text" name="narration"
                       class="form-control"
                       value="{{ old('narration', $voucher->narration ?? '') }}"
                       placeholder="Brief description of this voucher">
            </div>
        </div>
    </div>
</div>"""

new_narration = """            {{-- Paid To / Received From (payment/receipt vouchers only) --}}
            @php
                $partyLabel = match($voucherType) {
                    'cash_payment','bank_payment' => 'Paid To',
                    'cash_receipt','bank_receipt' => 'Received From',
                    default => null,
                };
                $partyTypes = ['cash_payment','bank_payment','cash_receipt','bank_receipt'];
            @endphp
            @if(in_array($voucherType, $partyTypes))
            <div class="col-12 col-sm-6 col-md-3">
                <label class="form-label fw-semibold">{{ $partyLabel }}</label>
                <input type="hidden" name="party_id"   id="partyId"   value="{{ old('party_id',   $voucher->party_id   ?? '') }}">
                <input type="hidden" name="party_type" id="partyType" value="{{ old('party_type', $voucher->party_type ?? '') }}">
                <select id="partySelect" style="width:100%"></select>
            </div>
            @endif

            {{-- Narration --}}
            <div class="col-12 col-md-4">
                <label class="form-label fw-semibold">Narration</label>
                <input type="text" name="narration"
                       class="form-control"
                       value="{{ old('narration', $voucher->narration ?? '') }}"
                       placeholder="Brief description of this voucher">
            </div>
        </div>
    </div>
</div>"""

content = content.replace(old_narration, new_narration, 1)

# Add Select2 AJAX init for party in @push('scripts')
old_ready = """// ── Init Select2 on load ──────────────────────────────────────────────────────
$(document).ready(function() {
    document.querySelectorAll('.voucher-line').forEach(row => initSelect2OnRow(row));
    recalcBalance();
});"""

new_ready = """// ── Init Select2 on load ──────────────────────────────────────────────────────
$(document).ready(function() {
    document.querySelectorAll('.voucher-line').forEach(row => initSelect2OnRow(row));
    recalcBalance();

    // ── Party Select2 (Paid To / Received From) ───────────────────────────────
    const partyEl = document.getElementById('partySelect');
    if (partyEl && typeof $.fn.select2 !== 'undefined') {
        const partyTypeColors = {
            'Customer':   '#1D4ED8',
            'Vendor':     '#DC2626',
            'Employee':   '#15803D',
            'Other Name': '#7C3AED',
        };

        function formatPartyOption(item) {
            if (!item.id) return item.text;
            const color = partyTypeColors[item.type] || '#374151';
            return $('<span>' +
                '<span style="display:inline-block;font-size:10px;padding:1px 6px;border-radius:8px;' +
                'background:' + color + '20;color:' + color + ';font-weight:600;margin-right:6px">' +
                (item.type || '') + '</span>' + item.text + '</span>');
        }

        $('#partySelect').select2({
            placeholder: '— Search customer, vendor, employee…',
            allowClear: true,
            minimumInputLength: 0,
            width: '100%',
            dropdownParent: $('body'),
            ajax: {
                url: '{{ route("party.search") }}',
                dataType: 'json',
                delay: 250,
                data: params => ({ q: params.term || '' }),
                processResults: data => ({ results: data.results }),
                cache: true,
            },
            templateResult: formatPartyOption,
            templateSelection: item => item.text || item.id,
        });

        // Pre-fill if editing existing voucher
        const existingPartyId   = document.getElementById('partyId')?.value;
        const existingPartyType = document.getElementById('partyType')?.value;
        if (existingPartyId && existingPartyType) {
            $.ajax({
                url: '{{ route("party.search") }}',
                data: { q: '' },
                success: function(data) {
                    const match = data.results.find(r =>
                        r.party_id == existingPartyId && r.party_type === existingPartyType
                    );
                    if (match) {
                        const opt = new Option(match.text, match.id, true, true);
                        $('#partySelect').append(opt).trigger('change');
                    }
                }
            });
        }

        // On change: update hidden inputs
        $('#partySelect').on('select2:select', function(e) {
            const d = e.params.data;
            document.getElementById('partyId').value   = d.party_id   || '';
            document.getElementById('partyType').value = d.party_type || '';
        });

        $('#partySelect').on('select2:unselect', function() {
            document.getElementById('partyId').value   = '';
            document.getElementById('partyType').value = '';
        });
    }
});"""

content = content.replace(old_ready, new_ready)
open('resources/views/accounting/vouchers/create.blade.php','w').write(content)
print("  create.blade.php updated.")
PYEOF

# ── 4. Update show.blade.php to display party name ───────────────────────────
echo "Step 4: Updating show view to display party..."
python3 << 'PYEOF'
content = open('resources/views/accounting/vouchers/show.blade.php').read()

# Add party display in screen summary
old_meta = """                    @if($voucher->reference)
                    <div class="col-6 col-md-3"><div class="text-muted mb-1" style="font-size:12px">Reference</div><div>{{ $voucher->reference }}</div></div>
                    @endif"""

new_meta = """                    @if($voucher->party_id && $voucher->party_type)
                    @php
                        $partyLabel = match($voucherType) {
                            'cash_payment','bank_payment' => 'Paid To',
                            'cash_receipt','bank_receipt' => 'Received From',
                            default => 'Party',
                        };
                        $partyName = match($voucher->party_type) {
                            'customer'   => \\App\\Models\\Customer::withoutGlobalScopes()->find($voucher->party_id)?->name,
                            'vendor'     => \\App\\Models\\Vendor::withoutGlobalScopes()->find($voucher->party_id)?->name,
                            'employee'   => \\App\\Models\\Employee::withoutGlobalScopes()->find($voucher->party_id)?->name,
                            'other_name' => \\App\\Models\\OtherName::withoutGlobalScopes()->find($voucher->party_id)?->name,
                            default      => null,
                        };
                        $partyTypeLabel = ucfirst(str_replace('_',' ',$voucher->party_type));
                    @endphp
                    @if($partyName)
                    <div class="col-6 col-md-3">
                        <div class="text-muted mb-1" style="font-size:12px">{{ $partyLabel }}</div>
                        <div class="fw-semibold">{{ $partyName }}</div>
                        <div class="text-muted" style="font-size:11.5px">{{ $partyTypeLabel }}</div>
                    </div>
                    @endif
                    @endif
                    @if($voucher->reference)
                    <div class="col-6 col-md-3"><div class="text-muted mb-1" style="font-size:12px">Reference</div><div>{{ $voucher->reference }}</div></div>
                    @endif"""

content = content.replace(old_meta, new_meta, 1)

# Add party to print meta
old_print_meta = """        @if($voucher->reference)
        <div class="vp-meta-row">
            <span class="vp-meta-label">Reference</span>
            <span class="vp-meta-value">: {{ $voucher->reference }}</span>
        </div>
        @endif"""

new_print_meta = """        @if($voucher->party_id && $voucher->party_type)
        @php
            $pLabel = match($voucherType) {
                'cash_payment','bank_payment' => 'Payee Name',
                'cash_receipt','bank_receipt' => 'Received From',
                default => 'Party',
            };
            $pName = match($voucher->party_type) {
                'customer'   => \\App\\Models\\Customer::withoutGlobalScopes()->find($voucher->party_id)?->name,
                'vendor'     => \\App\\Models\\Vendor::withoutGlobalScopes()->find($voucher->party_id)?->name,
                'employee'   => \\App\\Models\\Employee::withoutGlobalScopes()->find($voucher->party_id)?->name,
                'other_name' => \\App\\Models\\OtherName::withoutGlobalScopes()->find($voucher->party_id)?->name,
                default      => null,
            };
        @endphp
        @if($pName)
        <div class="vp-meta-row" style="grid-column:1/-1">
            <span class="vp-meta-label">{{ $pLabel }}</span>
            <span class="vp-meta-value">: {{ $pName }}</span>
        </div>
        @endif
        @endif
        @if($voucher->reference)
        <div class="vp-meta-row">
            <span class="vp-meta-label">Reference</span>
            <span class="vp-meta-value">: {{ $voucher->reference }}</span>
        </div>
        @endif"""

content = content.replace(old_print_meta, new_print_meta, 1)

open('resources/views/accounting/vouchers/show.blade.php','w').write(content)
print("  show.blade.php updated.")
PYEOF

# ── 5. Copy create to edit ────────────────────────────────────────────────────
echo "Step 5: Syncing edit view..."
cp resources/views/accounting/vouchers/create.blade.php \
   resources/views/accounting/vouchers/edit.blade.php

# ── 6. Clear cache ────────────────────────────────────────────────────────────
echo "Step 6: Clearing cache..."
php artisan view:clear
php artisan route:clear
php artisan optimize

echo ""
echo "=============================================="
echo "  DEPLOY COMPLETE!"
echo "=============================================="
echo ""
echo "  Party field added to:"
echo "  ✅ Cash Payment   → 'Paid To' field"
echo "  ✅ Bank Payment   → 'Paid To' field"
echo "  ✅ Cash Receipt   → 'Received From' field"
echo "  ✅ Bank Receipt   → 'Received From' field"
echo ""
echo "  Dropdown shows all 4 party types:"
echo "  🔵 Customer   (blue badge)"
echo "  🔴 Vendor     (red badge)"
echo "  🟢 Employee   (green badge)"
echo "  🟣 Other Name (purple badge)"
echo ""
echo "  Searchable with Select2 AJAX"
echo "  Shown on print as 'Payee Name' / 'Received From'"
echo "=============================================="
