<?php

namespace App\Imports\QuickBooks;

use App\Imports\QuickBooks\Concerns\SkipsQuickBooksExtraSheets;
use App\Imports\QuickBooks\Concerns\InteractsWithQuickBooksRows;
use App\Models\Account;
use App\Support\QuickBooksDesktopImportMapper;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\SkipsUnknownSheets;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;

class QuickBooksCoaImport implements WithMultipleSheets, SkipsUnknownSheets
{
    use SkipsQuickBooksExtraSheets;

    public readonly QuickBooksCoaSheetImport $sheet;

    private readonly string $sheetName;

    public function __construct(int $companyId, string $sheetName = 'Sheet1')
    {
        $this->sheetName = $sheetName;
        $this->sheet = new QuickBooksCoaSheetImport($companyId);
    }

    public function sheets(): array
    {
        return [$this->sheetName => $this->sheet];
    }
}

class QuickBooksCoaSheetImport implements ToCollection, WithHeadingRow
{
    use InteractsWithQuickBooksRows;

    public int $created = 0;
    public int $updated = 0;
    public int $skipped = 0;
    public array $errors = [];

    public function __construct(private readonly int $companyId)
    {
    }

    public function collection(Collection $rows): void
    {
        foreach ($rows as $offset => $row) {
            $this->importRow($this->normalizeRow($row), $offset + 2);
        }
    }

    private function importRow(array $row, int $line): void
    {
        $name = $this->clean($this->value($row, ['account']));
        $type = $this->clean($this->value($row, ['type']));

        if ($name === '') {
            $this->skipped++;
            return;
        }

        $classification = QuickBooksDesktopImportMapper::classificationFromAccountType($type, $name);

        if (!$classification) {
            $this->skipped++;
            return;
        }

        $account = Account::withoutGlobalScopes()
            ->where('company_id', $this->companyId)
            ->whereNull('deleted_at')
            ->where('name', $name)
            ->first();

        $isNew = !$account;
        $account ??= new Account(['company_id' => $this->companyId, 'is_system' => false]);

        $account->fill([
            'name' => $name,
            'type' => $classification['type'],
            'sub_type' => $classification['sub_type'],
            'detail_type' => $classification['detail_type'],
            'description' => $this->clean($this->value($row, ['description'])) ?: null,
            'is_group' => false,
            'is_active' => true,
            'is_bank' => $classification['is_bank'],
            'is_cash' => $classification['is_cash'],
            'depth' => 0,
            'path' => null,
            'parent_id' => null,
        ]);

        try {
            $account->save();
            $isNew ? $this->created++ : $this->updated++;
        } catch (\Throwable $e) {
            $this->errors[] = "Row {$line}: {$e->getMessage()}";
        }
    }
}
