<?php
namespace App\Repositories;

use App\Repositories\Contracts\BaseRepositoryContract;
use App\Traits\FileHandlerTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Schema;

abstract class BaseRepository implements BaseRepositoryContract
{
    use FileHandlerTrait;
    protected Model $model;


    public function __construct(Model $model)
    {
        $this->model = $model;
    }

    public function find(int | string $id, array $columns = ['*']): ?Model
    {
        return $this->model->newQuery()->find($id, $columns);
    }

    public function create(array $attributes): Model
    {
        return $this->model->newQuery()->create($attributes);
    }

    public function update(Model $model, array $attributes): bool
    {
        return $model->update($attributes);
    }

    public function statusToggle($model, string $reason = '', $column = 'is_active', array $relations = []): array
    {
        $newStatus = ! $model->{$column};

        $updateData = [$column => $newStatus];

        if ($reason && $this->hasReasonColumn($model)) {
            $updateData['reason'] = $reason;
        }

        if ($newStatus === true || empty($relations)) {
            $model->update($updateData);
            return [
                'success'   => true,
                'message'   => __('app.status_updated'),
                'relations' => [],
            ];
        }

        $relatedData = [];
        foreach ($relations as $relation) {
            if (method_exists($model, $relation)) {
                $count = $model->{$relation}()->count();
                if ($count > 0) {
                    $relatedData[$relation] = $count;
                }
            }
        }

        if (! empty($relatedData)) {
            return [
                'success'   => false,
                'message'   => __('app.cannot_deactive'),
                'relations' => $relatedData,
            ];
        }

        $model->update($updateData);
        return [
            'success'   => true,
            'message'   => __('app.status_updated'),
            'relations' => [],
        ];
    }

    private function hasReasonColumn($model): bool
    {
        return in_array('reason', $model->getFillable())
        || Schema::hasColumn($model->getTable(), 'reason');
    }


    public function delete(Model $model, array $relations = []): array
    {
        if (empty($relations)) {
            $model->delete();
            return [
                'success'   => true,
                'message'   => 'Deleted successfully',
                'relations' => [],
            ];
        }

        $relatedData = [];
        foreach ($relations as $relation) {
            if (method_exists($model, $relation)) {
                $count = $model->{$relation}()->count();
                if ($count > 0) {
                    $relatedData[$relation] = $count;
                }
            }
        }

        if (! empty($relatedData)) {
            return [
                'success'   => false,
                'message'   => 'Cannot delete record with existing relations',
                'relations' => $relatedData,
            ];
        }

        $model->delete();
        return [
            'success'   => true,
            'message'   => 'Deleted successfully',
            'relations' => [],
        ];
    }


    public function bulkDelete(array $ids, array $relations = [])
    {
        $deleted        = 0;
        $skipped        = 0;
        $skippedIds     = [];
        $skippedRecords = [];

        if (empty($relations)) {
            $deleted = $this->model->whereIn('id', $ids)->delete();
            return [
                'deleted'         => $deleted,
                'skipped'         => 0,
                'skipped_ids'     => [],
                'skipped_records' => [],
            ];
        }

        $records = $this->model->whereIn('id', $ids)->get();

        foreach ($records as $record) {
            $hasRelations = false;
            $relatedData  = [];

            foreach ($relations as $relation) {
                if (method_exists($record, $relation)) {
                    $count = $record->{$relation}()->count();
                    if ($count > 0) {
                        $hasRelations           = true;
                        $relatedData[$relation] = $count;
                    }
                }
            }

            if ($hasRelations) {
                $skipped++;
                $skippedIds[]     = $record->id;
                $skippedRecords[] = [
                    'id'   => $record->id,
                    'name' => $record->name ?? $record->trade_name ?? $record->title ?? "ID: {$record->id}",
                    'relations' => $relatedData,
                ];
            } else {
                $record->delete();
                $deleted++;
            }
        }

        return [
            'deleted'         => $deleted,
            'skipped'         => $skipped,
            'skipped_ids'     => $skippedIds,
            'skipped_records' => $skippedRecords,
        ];
    }


    public function bulkStatus(array $ids, bool $status, string $column = 'is_active', array $relations = [])
    {
        $updated        = 0;
        $skipped        = 0;
        $skippedIds     = [];
        $skippedRecords = [];

        if ($status === true || empty($relations)) {
            $updated = $this->model->whereIn('id', $ids)->update([$column => $status]);
            return [
                'updated'         => $updated,
                'skipped'         => 0,
                'skipped_ids'     => [],
                'skipped_records' => [],
            ];
        }

        // Only check relations when deactivating (status = false)
        $records = $this->model->whereIn('id', $ids)->get();

        foreach ($records as $record) {
            $hasRelations = false;
            $relatedData  = [];

            foreach ($relations as $relation) {
                if (method_exists($record, $relation)) {
                    $count = $record->{$relation}()->count();
                    if ($count > 0) {
                        $hasRelations           = true;
                        $relatedData[$relation] = $count;
                    }
                }
            }

            if ($hasRelations) {
                $skipped++;
                $skippedIds[]     = $record->id;
                $skippedRecords[] = [
                    'id'   => $record->id,
                    'name' => $record->name ?? $record->trade_name ?? $record->title ?? "ID: {$record->id}",
                    'relations' => $relatedData,
                ];
            } else {
                $record->update([$column => $status]);
                $updated++;
            }
        }

        return [
            'updated'         => $updated,
            'skipped'         => $skipped,
            'skipped_ids'     => $skippedIds,
            'skipped_records' => $skippedRecords,
        ];
    }
}
