<?php

namespace App\Repositories;

use App\Models\{{modelName}};
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;

class {{modelName}}Repository
{
    /**
     * Get all items with filtering
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Pagination\LengthAwarePaginator
     */
    public function getAll(Request $request)
    {
        $query = {{modelName}}::query();
        
        // Apply filters
        if ($request->has('search')) {
            $searchTerm = $request->search;
            $query->where(function (Builder $q) use ($searchTerm) {
                {{#searchableFields}}
                $q->orWhere('{{.}}', 'like', "%{$searchTerm}%");
                {{/searchableFields}}
            });
        }
        
        // Apply specific column filters
        {{#fields}}
        if ($request->has('{{name}}')) {
            $query->where('{{name}}', $request->{{name}});
        }
        {{/fields}}
        
        // Include relationships
        $query->with([
            {{#relationships}}
            {{#isBelongsTo}}'{{name}}',{{/isBelongsTo}}
            {{#isHasOne}}'{{name}}',{{/isHasOne}}
            {{/relationships}}
        ]);
        
        // Sorting
        $sortField = $request->input('sort_field', 'id');
        $sortDirection = $request->input('sort_direction', 'desc');
        $query->orderBy($sortField, $sortDirection);
        
        // Pagination
        $perPage = $request->input('per_page', 15);
        return $query->paginate($perPage);
    }
    
    /**
     * Create a new item
     *
     * @param  array  $data
     * @return \App\Models\{{modelName}}
     */
    public function create(array $data)
    {
        ${{camelCase}} = {{modelName}}::create($data);
        
        // Load relationships after creation
        ${{camelCase}}->load([
            {{#relationships}}
            {{#isBelongsTo}}'{{name}}',{{/isBelongsTo}}
            {{#isHasOne}}'{{name}}',{{/isHasOne}}
            {{/relationships}}
        ]);
        
        return ${{camelCase}};
    }
    
    /**
     * Update an existing item
     *
     * @param  \App\Models\{{modelName}}  ${{camelCase}}
     * @param  array  $data
     * @return \App\Models\{{modelName}}
     */
    public function update({{modelName}} ${{camelCase}}, array $data)
    {
        ${{camelCase}}->update($data);
        
        // Load relationships after update
        ${{camelCase}}->load([
            {{#relationships}}
            {{#isBelongsTo}}'{{name}}',{{/isBelongsTo}}
            {{#isHasOne}}'{{name}}',{{/isHasOne}}
            {{/relationships}}
        ]);
        
        return ${{camelCase}};
    }
    
    /**
     * Delete an item
     *
     * @param  \App\Models\{{modelName}}  ${{camelCase}}
     * @return bool|null
     */
    public function delete({{modelName}} ${{camelCase}})
    {
        return ${{camelCase}}->delete();
    }

{{#relationships}}
{{#isHasMany}}
    /**
     * Sync {{name}} relationship
     *
     * @param  \App\Models\{{modelName}}  ${{camelCase}}
     * @param  array  $ids
     * @return void
     */
    public function sync{{pascalName}}({{modelName}} ${{camelCase}}, array $ids)
    {
        // This is a hasMany relationship, we need to update the foreign keys
        // in the related models to point to this model
        $foreignKey = '{{foreignKey}}';
        
        // Get the related model class
        $relatedModel = get_class(${{camelCase}}->{{name}}()->getRelated());
        
        // First, remove all associations by setting foreign key to null
        $relatedModel::where($foreignKey, ${{camelCase}}->id)->update([$foreignKey => null]);
        
        // Then, associate the provided IDs
        if (!empty($ids)) {
            $relatedModel::whereIn('id', $ids)->update([$foreignKey => ${{camelCase}}->id]);
        }
    }
{{/isHasMany}}

{{#isHasOne}}
    /**
     * Update {{name}} relationship
     *
     * @param  \App\Models\{{modelName}}  ${{camelCase}}
     * @param  int  $id
     * @return void
     */
    public function update{{pascalName}}({{modelName}} ${{camelCase}}, int $id)
    {
        // This is a hasOne relationship, we need to update the foreign key
        // in the related model to point to this model
        $foreignKey = '{{foreignKey}}';
        
        // Get the related model class
        $relatedModel = get_class(${{camelCase}}->{{name}}()->getRelated());
        
        // First, remove any existing association by setting foreign key to null
        $relatedModel::where($foreignKey, ${{camelCase}}->id)->update([$foreignKey => null]);
        
        // Then, associate the provided ID
        $relatedModel::where('id', $id)->update([$foreignKey => ${{camelCase}}->id]);
    }
{{/isHasOne}}

{{#isBelongsToMany}}
    /**
     * Sync {{name}} relationship
     *
     * @param  \App\Models\{{modelName}}  ${{camelCase}}
     * @param  array  $ids
     * @param  array  $pivotData
     * @return void
     */
    public function sync{{pascalName}}({{modelName}} ${{camelCase}}, array $ids, array $pivotData = [])
    {
        // For a belongsToMany relationship, we can use the sync method
        // which handles attaching and detaching automatically
        $syncData = [];
        
        foreach ($ids as $id) {
            $syncData[$id] = $pivotData[$id] ?? [];
        }
        
        ${{camelCase}}->{{name}}()->sync($syncData);
    }
{{/isBelongsToMany}}
{{/relationships}}
}