<?php

namespace App\Http\Controllers;

use App\Http\Resources\DefaultCollection;
use App\Http\Resources\DefaultResource;
use App\Models\Admin\Interna;
use App\Models\Admin\Modulos;
use App\Models\Difusion;
use App\Models\DifusionModulos;
use App\Models\Promociones;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class DifusionController extends Controller
{
    private array $valid_models = [
        'novedades' => Interna::class,
        'promociones' => Promociones::class,
    ];

    public function index(): DefaultCollection
    {
        $size = request('page.size', 10);
        $page = request('page.number', 1);

        $result = Difusion::query()
            ->selectFillable()
            ->with(['grupos', 'suscriptores'])
            ->filterLike(request('filter', []))
            ->applySorts(request('sort'))
            ->latest()
            ->paginate(
                $perPage = $size,
                $columns = ['titulo'],
                $pageName = 'page[number]',
                $page = $page
            )->appends(request()->only(
                'sort',
                'page.size',
                'filter'
            ));

        return DefaultCollection::make($result);
    }

    public function store(Request $request): DefaultResource
    {
        DB::beginTransaction();
        try {

            $grupos_difusion_ids = $request->get('grupos_ids', []);
            $modulos = $this->filtrarDuplicados($request->get('modulos', []));
            //Obtenemos a los integrantes de esos grupos
            $integrantes_grupos_ids = $this->getIntegrantesGrupos($grupos_difusion_ids);

            $input = array_merge($request->all(), [
                'slug' => str_slug($request->get('asunto', ''))
            ]);

            unset($input['modulos']);
            unset($input['grupos_difusion_ids']);

            $result = Difusion::create($input);
            $result->grupos()->attach($grupos_difusion_ids);
            $result->suscriptores()->attach($integrantes_grupos_ids);
            $result->setModulos($modulos);

            DB::commit();
            return DefaultResource::make($result);
        } catch (Exception $e) {
            DB::rollBack();
            Log::error(json_encode($e->getMessage()));
            return response('Lo sentimos, tenemos un inconveniente temporal', 422);
        }
    }

    public function edit($id)
    {
        $result = Difusion::find($id)->first();
        $result->grupos_ids = $result->grupos()->get()->pluck('id');
        $result->modulos =  DifusionModulos::where('difusion_id', $id)
            ->get()->each(function ($item) {
                $item->modulo = array_search($item->modulo_type, $this->valid_models);
            });



        return DefaultResource::make($result);
    }

    public function update(Request $request, $id): DefaultResource
    {
        DB::beginTransaction();
        try {
            $result = Difusion::find($id);
            if ($result->enviar || $result->enviado) {
                //No se puede enviar
                return response('Lo sentimos, su correo está en proceso de enviado y no puede ser modificado', 422);
            }

            $grupos_difusion_ids = $request->get('grupos_ids', []);
            $modulos = $this->filtrarDuplicados($request->get('modulos', []));

            //Obtenemos a los integrantes de esos grupos
            $integrantes_grupos_ids = $this->getIntegrantesGrupos($grupos_difusion_ids);

            $input = array_merge($request->all(), [
                'slug' => str_slug($request->get('asunto', ''))
            ]);

            unset($input['modulos']);
            unset($input['grupos_difusion_ids']);

            $result->fill($input)->save();
            $result->grupos()->sync($grupos_difusion_ids);
            $result->suscriptores()->sync($integrantes_grupos_ids);
            $result->setModulos($modulos);

            DB::commit();
            return DefaultResource::make($result);
        } catch (Exception $e) {
            DB::rollBack();
            Log::error(json_encode($e->getMessage()));
            return response('Lo sentimos, tenemos un inconveniente temporal', 422);
        }
    }

    public function destroy($id): Response
    {
        Difusion::destroy($id);
        return response()->noContent();
    }

    public function getModulos(): array
    {
        $modulo = Modulos::slug('novedades')
            ->activo()
            ->selectFillable()
            ->first();

        return [
            [
                'slug' => 'novedades',
                'titulo' => 'Novedades',
                'children' => Interna::modulo($modulo->id)
                    ->where('operadores', false)
                    ->select('id', 'titulo')
                    ->activo()
                    ->get(),
            ],
            [
                'slug' => 'promociones',
                'titulo' => 'Promociones',
                'children' => Promociones::where('operadores', false)
                    ->select('id', 'titulo')
                    ->where('fecha_desde', '<=', Carbon::now())
                    ->where('fecha_hasta', '>=', Carbon::now()->subDay())
                    ->activo()
                    ->get(),
            ],
        ];
    }

    private function filtrarDuplicados($array)
    {
        $modulosFiltrados = [];
        foreach ($array as $obj) {
            $encontrado = false;
            foreach ($modulosFiltrados as $item) {
                if ($item['modulo'] === $obj['modulo'] && $item['modulo_id'] === $obj['modulo_id']) {
                    $encontrado = true;
                    break;
                }
            }
            if (!$encontrado) {
                $modulosFiltrados[] = $obj;
            }
        }
        foreach ($modulosFiltrados as $k => $obj) {
            $modulosFiltrados[$k] = (object) [
                'modulo_id' => $obj['modulo_id'],
                'modulo_type' => $this->valid_models[$obj['modulo']],
            ];
        }
        return $modulosFiltrados;
    }

    private function getIntegrantesGrupos($array)
    {
        return DB::table('listas_difusion as ld')
            ->join('grupos_suscriptores_listas_difusion as gsld', 'gsld.lista_difusion_id', 'ld.id')
            ->whereIn('gsld.grupo_suscriptor_id', $array)
            ->groupBy('ld.id')
            ->select('ld.id')
            ->get()
            ->pluck('id');
    }
}
