<?php

namespace App\Core\Service;

use App;
use Illuminate\Support\Facades\Log;
use Exception;
use App\Exceptions\ApiErrorException;
use App\Core\Repository\PropertyCompetitorGroup\PropertyCompetitorGroupRepository;
use App\Core\Repository\PropertyCompetitorGroupMapping\PropertyCompetitorGroupMappingRepository;

class PropertyCompetitorGroupService
{

    private $propertyCompetitorGroupRepository;
    private $propertyCompetitorGroupMappingRepository;

    public function __construct(
        PropertyCompetitorGroupRepository $propertyCompetitorGroupRepository,
        PropertyCompetitorGroupMappingRepository $propertyCompetitorGroupMappingRepository
    )
    {
        $this->propertyCompetitorGroupRepository = $propertyCompetitorGroupRepository;
        $this->propertyCompetitorGroupMappingRepository = $propertyCompetitorGroupMappingRepository;
    }

    public function createPropertyCompetitorGroup($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $insertData = [
                "property_id" => fillOnUndefined($param, "property_id"),
                "name" => fillOnUndefined($param, "name"),
                "status" => fillOnUndefined($param, "status", 1),
                "created_by" => fillOnUndefined($param, "created_by"),
                "updated_by" => fillOnUndefined($param, "updated_by"),
                "created_at" => time(),
                "updated_at" => time(),
            ];

            $insertDataResult = $this->propertyCompetitorGroupRepository->create($insertData);
            if ($insertDataResult['status'] != 'success') {
                throw new Exception($insertDataResult['message']);
            }

            $insertDataResult = $insertDataResult["data"];

            $response = [
                'status' => true,
                'data' => $insertDataResult,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = 'api-unknown_error';
        }

        return output($response);
    }

    public function selectPropertyCompetitorGroup($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->propertyCompetitorGroupRepository->findByCriteria($param, $column);

            $propertyList = [];
            foreach ($data as $property) {
                $propertyList[] = [
                    'id' => $property['id'],
                    'property_id' => $property['property_id'],
                    'name' => $property['name'],
                    'status' => $property['status'],
                ];
            }

            $response = [
                'status' => true,
                'data' => $propertyList,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function syncPropertyCompetitorGroup($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $id = fillOnUndefined($param, "id");
            $propertyId = fillOnUndefined($param, "property_id");
            $name = fillOnUndefined($param, "name");
            $status = fillOnUndefined($param, "status", 1);
            $userId = fillOnUndefined($param, "user_id");

            if ($id) {
                // Güncelleme öncesi: kayıt ve yetki kontrolü
                $existingRow = $this->propertyCompetitorGroupRepository->findByCriteria([
                    'criteria' => [
                        ['field' => 'id', 'condition' => '=', 'value' => $id],
                    ],
                    'firstRow' => 1
                ], ['id','property_id']);

                if (!$existingRow) {
                    throw new ApiErrorException('Record not found');
                }

                // Eğer dışarıdan property_id gönderildiyse, kayıtla eşleşmesini zorunlu tutalım
                if (!is_null($propertyId) && (int)$propertyId !== (int)$existingRow['property_id']) {
                    // Bu durum, kullanıcının farklı bir property_id ile kayıt güncellemeye çalıştığını gösterir
                    throw new ApiErrorException('Permission denied for this property');
                }

                // Güvenlik: update sırasında property_id değiştirilmesin
                $updateData = [
                    "name" => $name,
                    "status" => $status,
                    "updated_by" => $userId,
                    "updated_at" => time(),
                ];

                // Repository update signature: update($id, $data)
                $updateResult = $this->propertyCompetitorGroupRepository->update($id, $updateData);
                if ($updateResult['status'] != 'success') {
                    throw new Exception($updateResult['message']);
                }
                $data = $updateResult["data"];
            } else {
                // Ekleme
                $insertData = [
                    "property_id" => $propertyId,
                    "name" => $name,
                    "status" => $status,
                    "created_by" => $userId,
                    "updated_by" => $userId,
                    "created_at" => time(),
                    "updated_at" => time(),
                ];

                $insertResult = $this->propertyCompetitorGroupRepository->create($insertData);
                if ($insertResult['status'] != 'success') {
                    throw new Exception($insertResult['message']);
                }
                $data = $insertResult["data"];
            }

            $response = [
                'status' => true,
                'data' => $data,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = 'api-unknown_error';
        }

        return output($response);
    }

    public function deletePropertyCompetitorGroup($deleteThisId)
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $deleteThisId = is_array($deleteThisId) ? $deleteThisId : [$deleteThisId];
            $deleteThisArray = $this->propertyCompetitorGroupRepository->destroy($deleteThisId);

            if ($deleteThisArray['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            $response = [
                'status' => true,
                'data' => null,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    /**
     * Mapping GET
     * GET isteklerinde meta alanlar (created_by, updated_by, created_at, updated_at) gizlenir.
     */
    public function getPropertyCompetitorGroupMapping($param = [], $columns = [
        'id',
        'competitor_group_id',
        'property_id',
        'competitor_property_source',
        'competitor_property_key',
        'status',
    ])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {
            $propertyId = fillOnUndefined($param, 'property_id');
            $competitorGroupId = fillOnUndefined($param, 'competitor_group_id');

            if (!$propertyId || !$competitorGroupId) {
                throw new ApiErrorException('property_id and competitor_group_id are required');
            }

            $selectParams = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                    ['field' => 'competitor_group_id', 'condition' => '=', 'value' => $competitorGroupId],
                ]
            ];

            $data = $this->propertyCompetitorGroupMappingRepository->findByCriteria($selectParams, $columns);

            $response = [
                'status' => true,
                'data' => $data,
            ];
        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage();
            Log::error($message);
            $response['message'] = 'api-unknown_error';
        }

        return output($response);
    }

    /**
     * Mapping SYNC
     * Tam senkron: önce mevcutları sil, sonra yeni gelenleri ekle.
     * Dönüşte ilgili kayıtları (meta alanlar dahil) array olarak döndürür.
     */
    public function syncPropertyCompetitorGroupMapping($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {
            $propertyId = fillOnUndefined($param, 'property_id');
            $competitorGroupId = fillOnUndefined($param, 'competitor_group_id');
            $competitors = fillOnUndefined($param, 'competitor', []);
            $userId = fillOnUndefined($param, 'user_id');

            if (!$propertyId || !$competitorGroupId) {
                throw new ApiErrorException('property_id and competitor_group_id are required');
            }

            // YETKİ KONTROLÜ: competitor_group_id gerçekten bu property_id'ye ait mi?
            // Kullanıcı, farklı bir gruba (başka property'ye ait) yazmaya çalışırsa engelle.
            $groupRow = $this->propertyCompetitorGroupRepository->findByCriteria([
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $competitorGroupId],
                ],
                'firstRow' => 1
            ], ['id', 'property_id']);

            if (!$groupRow) {
                throw new ApiErrorException('Competitor group not found');
            }

            if ((int)$groupRow['property_id'] !== (int)$propertyId) {
                // İstenen davranış: kullanıcı farklı bir grup ID gönderirse ve bu grup bu property'e ait değilse izin verme
                throw new ApiErrorException('Permission denied for this competitor group');
            }

            // 1) Eski kayıtları temizle (tam eşitleme) — yalnızca ilgili property_id + competitor_group_id çiftini hedefle
            // Not: Repository delete() metodunda filtre anahtarı 'criteria' olmalı; 'where' kullanılırsa tüm kayıtlar silinebilir.
            $deleteWhere = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                    ['field' => 'competitor_group_id', 'condition' => '=', 'value' => $competitorGroupId],
                ]
            ];
            $deleteResult = $this->propertyCompetitorGroupMappingRepository->delete($deleteWhere);
            if (($deleteResult['status'] ?? 'success') !== 'success') {
                throw new Exception($deleteResult['message'] ?? 'delete_error');
            }

            // 2) Yeni kayıtları ekle
            $now = time();
            $rows = [];
            foreach ($competitors as $c) {
                $source = $c['source'] ?? 'extranetwork';
                $key = $c['key'] ?? null;
                if (!$key) { // key zorunlu
                    continue;
                }
                $rows[] = [
                    'competitor_group_id' => $competitorGroupId,
                    'property_id' => $propertyId,
                    'competitor_property_source' => $source ?: 'extranetwork',
                    'competitor_property_key' => (string)$key,
                    'status' => 1,
                    'created_by' => $userId,
                    'updated_by' => $userId,
                    'created_at' => $now,
                    'updated_at' => $now,
                ];
            }

            if (!empty($rows)) {
                $insertResult = $this->propertyCompetitorGroupMappingRepository->insert($rows);
                if (($insertResult['status'] ?? '') !== 'success') {
                    throw new Exception($insertResult['message'] ?? 'insert_error');
                }
            }

            // 3) Güncel kayıtları geri döndür
            $selectParams = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                    ['field' => 'competitor_group_id', 'condition' => '=', 'value' => $competitorGroupId],
                ]
            ];

            $columns = [
                'id',
                'competitor_group_id',
                'property_id',
                'competitor_property_source',
                'competitor_property_key',
                'status',
                'created_by',
                'updated_by',
                'created_at',
                'updated_at',
            ];

            $rowsResult = $this->propertyCompetitorGroupMappingRepository->findByCriteria($selectParams, $columns);

            $response = [
                'status' => true,
                'data' => $rowsResult,
            ];
        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage();
            Log::error($message);
            $response['message'] = 'api-unknown_error';
        }

        return output($response);
    }

}
