<?php

namespace App\Services;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

abstract class BaseService
{
    /**
     * The repository instance.
     */
    protected $repository;

    /**
     * Get all records with optional filters.
     */
    public function getAll(array $filters = [], array $with = [])
    {
        return $this->repository->getAll($filters, $with);
    }

    /**
     * Get paginated records.
     */
    public function getPaginated(array $filters = [], int $perPage = 15, array $with = [])
    {
        return $this->repository->getPaginated($filters, $perPage, $with);
    }

    /**
     * Find a record by ID.
     */
    public function findById($id, array $with = [])
    {
        return $this->repository->findById($id, $with);
    }

    /**
     * Find a record by specific field.
     */
    public function findBy(string $field, $value, array $with = [])
    {
        return $this->repository->findBy($field, $value, $with);
    }

    /**
     * Create a new record.
     */
    public function create(array $data)
    {
        DB::beginTransaction();
        try {
            $record = $this->repository->create($data);

            // Log the creation
            $this->logActivity('created', $record);

            DB::commit();
            return $record;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to create record in ' . get_class($this), [
                'data' => $data,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * Update a record.
     */
    public function update($id, array $data)
    {
        DB::beginTransaction();
        try {
            $record = $this->repository->update($id, $data);

            // Log the update
            $this->logActivity('updated', $record);

            DB::commit();
            return $record;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to update record in ' . get_class($this), [
                'id' => $id,
                'data' => $data,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * Delete a record.
     */
    public function delete($id)
    {
        DB::beginTransaction();
        try {
            $record = $this->findById($id);
            $result = $this->repository->delete($id);

            // Log the deletion
            $this->logActivity('deleted', $record);

            DB::commit();
            return $result;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to delete record in ' . get_class($this), [
                'id' => $id,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * Bulk create records.
     */
    public function bulkCreate(array $records)
    {
        DB::beginTransaction();
        try {
            $result = $this->repository->bulkCreate($records);

            // Log bulk creation
            Log::info('Bulk created records in ' . get_class($this), [
                'count' => count($records)
            ]);

            DB::commit();
            return $result;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to bulk create records in ' . get_class($this), [
                'count' => count($records),
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * Search records.
     */
    public function search(string $query, array $fields = [], int $perPage = 15)
    {
        return $this->repository->search($query, $fields, $perPage);
    }

    /**
     * Get records count.
     */
    public function count(array $filters = [])
    {
        return $this->repository->count($filters);
    }

    /**
     * Check if record exists.
     */
    public function exists($id)
    {
        return $this->repository->exists($id);
    }

    /**
     * Log activity for auditing.
     */
    protected function logActivity(string $action, Model $record = null)
    {
        if (!$record) {
            return;
        }

        $user = auth()->user();
        if (!$user) {
            return;
        }

        try {
            \App\Models\UserActivity::create([
                'user_id' => $user->id,
                'action' => $action,
                'description' => "User {$action} " . class_basename($record) . " #{$record->getKey()}",
                'properties' => [
                    'model' => get_class($record),
                    'model_id' => $record->getKey(),
                    'changes' => $record->getChanges(),
                ],
                'ip_address' => request()->ip(),
                'user_agent' => request()->userAgent(),
            ]);
        } catch (\Exception $e) {
            Log::warning('Failed to log activity', [
                'action' => $action,
                'model' => get_class($record),
                'error' => $e->getMessage()
            ]);
        }
    }

    /**
     * Validate business rules.
     */
    protected function validateBusinessRules(array $data, $id = null)
    {
        // Override in child classes for specific validation
        return true;
    }

    /**
     * Get service statistics.
     */
    public function getStats()
    {
        return [
            'total' => $this->count(),
            'active' => $this->count(['status' => 'active']),
        ];
    }
}