<?php

namespace App\Controllers\AdvertisementManager\Automation;

use App\Controllers\BaseController;
use App\Libraries\slack_api\SlackChat;
use App\Models\Advertiser\AdvGoogleManagerModel;
use App\Models\Advertiser\AutomationModel;
use App\Services\AdvLoggerService;
use App\ThirdParty\facebook_api\ZenithFB;
use App\ThirdParty\googleads_api\ZenithGG;
use App\ThirdParty\moment_api\ZenithKM;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\CLI\CLI;
use CodeIgniter\I18n\Time;
use DateTime;
use Exception;

class AutomationController extends BaseController
{
    use ResponseTrait;
    
    protected $automation, $google;

    public function __construct() 
    {
        $this->automation = model(AutomationModel::class);
        $this->google = model(AdvGoogleManagerModel::class);
    }

    public function index()
    {
        return view('automation/automation');
    }
    
    public function getList()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
            $arg = $this->request->getGet();
            $automations = $this->automation->getAutomationList($arg);
            $result = $this->automationList($automations);
            
            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    private function automationList($lists) {
        // 현재 시간을 설정
        $currentDate = new Time('now');
        
        // 목록의 각 항목을 순회
        foreach ($lists['data'] as &$data) {
            $closestTime = null;
            
            // 상태가 1이 아니면 예상 실행 시간을 빈 문자열로 설정하고 다음 항목으로 넘어감
            if (!isset($data['aa_status']) || $data['aa_status'] != 1) {
                $data['expected_time'] = '';
                continue;
            }
            
            // 스케줄 값을 변환
            $schedule = $this->convertJsonToTimes($data['aas_schedule_value']);
            $currentDay = $currentDate->format('N'); // 현재 요일 (1: 월요일, 7: 일요일)
            $currentTime = $currentDate->format('H:i'); // 현재 시간 (HH:MM)
            
            // 스케줄 탐색을 위한 요일 배열 생성 및 정렬
            $days = array_keys($schedule);
            sort($days);
            $found = false;

            // 이번 주 스케줄 탐색
            foreach ($days as $day) {
                // 오늘 실행된 항목이 있으면 현재 요일 이후의 스케줄을 계속 탐색
                if (!empty($data['aar_exec_timestamp_success'])) {
                    $execTimestampSuccess = Time::parse($data['aar_exec_timestamp_success']); // 실행 시간
                    $execDay = $execTimestampSuccess->format('N'); // 실행 시간의 요일
                    if ($data['aas_exec_once'] == 1 && $execDay == $day && $execDay == $currentDay) {
                        continue;
                    }
                }

                // 현재 요일 이후의 스케줄을 탐색하여 가장 가까운 시간을 찾음
                foreach ($schedule[$day] as $time) {
                    $scheduledTime = Time::parse($time);
                    $scheduledDateTime = $currentDate->setISODate($currentDate->year, $currentDate->weekOfYear, $day)->setTime($scheduledTime->hour, $scheduledTime->minute);

                    // 현재 시간 이후의 스케줄 시간 중 가장 가까운 시간을 찾음
                    if ($scheduledDateTime->isAfter($currentDate)) {
                        if (is_null($closestTime) || $scheduledDateTime->isBefore($closestTime)) {
                            $closestTime = $scheduledDateTime;
                            $found = true;
                        }
                    } else if ($scheduledDateTime->difference($currentDate)->getMinutes() <= 30) {
                        // 현재 시간과 30분 이내의 차이가 나는 스케줄 시간 중 가장 가까운 시간을 찾음
                        $interval = 5; // 5분 단위
                        $nextPossibleTime = $currentDate->addMinutes($interval - ($currentDate->getMinute() % $interval));
                        if ($nextPossibleTime->isAfter($currentDate) && (is_null($closestTime) || $nextPossibleTime->isBefore($closestTime))) {
                            $closestTime = $nextPossibleTime;
                            $found = true;
                        }
                    }
                }

                // 가장 가까운 시간을 찾았으면 루프를 종료
                if ($found) break;
            }

            // 이번 주에 실행할 스케줄이 없으면 다음 주 스케줄 탐색
            if (!$found) {
                foreach ($days as $day) {
                    foreach ($schedule[$day] as $time) {
                        $scheduledTime = Time::parse($time);
                        $scheduledDateTime = $currentDate->addDays(7 - $currentDay + $day)->setTime($scheduledTime->hour, $scheduledTime->minute);
                        if (is_null($closestTime) || $scheduledDateTime->isBefore($closestTime)) {
                            $closestTime = $scheduledDateTime;
                        }
                    }
                }
            }

            // 가장 가까운 시간을 예상 실행 시간으로 설정
            if (!is_null($closestTime)) {
                $data['expected_time'] = $closestTime->toDateTimeString();
            }
        }

        // 예상 실행 시간이 포함된 목록을 반환
        return $lists;
    }

    public function getAutomation()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
            $arg = $this->request->getGet();
            $result = $this->automation->getAutomation($arg);
            $result['aas_schedule_value'] = json_decode($result['aas_schedule_value']);
            if(!empty($result['targets'])){
                foreach ($result['targets'] as &$target) {
                    switch ($target['media']) {
                        case 'company':
                            $target['media'] = '광고주';
                            break;
                        case 'facebook':
                            $target['media'] = '페이스북';
                            break;
                        case 'google':
                            $target['media'] = '구글';
                            break;
                        case 'kakao':
                            $target['media'] = '카카오';
                            break;
                        default:
                            break;
                    }
    
                    switch ($target['type']) {
                        case 'advertiser':
                            $target['type'] = '광고주';
                            break;
                        case 'account':
                            $target['type'] = '매체광고주';
                            break;
                        case 'campaign':
                            $target['type'] = '캠페인';
                            break;
                        case 'adgroup':
                            $target['type'] = '광고그룹';
                            break;
                        case 'ad':
                            $target['type'] = '광고';
                            break;
                        default:
                            break;
                    }
    
                    if($target['status'] == 1 || $target['status'] == 'ON' || $target['status'] == 'ENABLED' || $target['status'] == 'ACTIVE'){
                        $target['status'] = '활성';
                    }else{
                        $target['status'] = '비활성';
                    }
                }
            }
            
            foreach ($result['executions'] as &$execution) {
                switch ($execution['media']) {
                    case 'facebook':
                        $execution['media'] = '페이스북';
                        break;
                    case 'google':
                        $execution['media'] = '구글';
                        break;
                    case 'kakao':
                        $execution['media'] = '카카오';
                        break;
                    default:
                        break;
                }

                switch ($execution['type']) {
                    case 'campaign':
                        $execution['type'] = '캠페인';
                        break;
                    case 'adgroup':
                        $execution['type'] = '광고그룹';
                        break;
                    case 'ad':
                        $execution['type'] = '광고';
                        break;
                    default:
                        break;
                }

                if($execution['status'] == 1 || $execution['status'] == 'ON' || $execution['status'] == 'ENABLED' || $execution['status'] == 'ACTIVE'){
                    $execution['status'] = '활성';
                }else{
                    $execution['status'] = '비활성';
                }
            }
            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function setStatus()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put'){
            $arg = $this->request->getRawInput();
            $data = [
                'seq' => $arg['seq'],
				'status' => $arg['status'],
            ];
            $result = $this->automation->setAutomationStatus($data);

            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function getAdv()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
            $arg = $this->request->getGet();
            switch ($arg['tab']) {
                case 'advertiser':
                    if(!empty($arg['adv'])){
                        $result = $this->automation->getSearchCompaniesWithAdv($arg); 
                    }else{
                        $result = $this->automation->getSearchCompanies($arg);  
                    }
                    break;
                case 'account':
                    if(!empty($arg['adv'])){
                        $result = $this->automation->getSearchAccountsWithAdv($arg); 
                    }else{
                        $result = $this->automation->getSearchAccounts($arg);  
                    }              
                    break;
                case 'campaign':
                    if(!empty($arg['adv'])){
                        $result = $this->automation->getSearchCampaignsWithAdv($arg); 
                    }else{
                        $result = $this->automation->getSearchCampaigns($arg);  
                    } 
                    break;
                case 'adgroup':
                    if(!empty($arg['adv'])){
                        $result = $this->automation->getSearchAdsetsWithAdv($arg); 
                    }else{
                        $result = $this->automation->getSearchAdsets($arg);  
                    } 
                    break;
                case 'ad':
                    if(!empty($arg['adv'])){
                        $result = $this->automation->getSearchAdsWithAdv($arg); 
                    }else{
                        $result = $this->automation->getSearchAds($arg);  
                    } 
                    break;
                default:
                    return $this->fail("잘못된 요청");
                    break;
            }

            foreach ($result['data'] as &$row) {
                if(isset($row['status']) && $row['status'] == 1 || $row['status'] == 'ON' || $row['status'] == 'ENABLED' || $row['status'] == 'ACTIVE'){
                    $row['status'] = '활성';
                }else{
                    $row['status'] = '비활성';
                }
            }

            $result = [
                'data' => $result['data'],
                'recordsTotal' => $result['allCount'],
                'recordsFiltered' => $result['allCount'],
                'draw' => intval($arg['draw']),
            ];

            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function getLogs()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
            $arg = $this->request->getGet();
            $result = $this->automation->getLogs($arg);                
            
            foreach ($result['data'] as &$data) {
                switch ($data['result']) {
                    case 'success':
                        $data['result'] = '실행됨';             
                        break;
                    case 'failed':
                        $data['result'] = '실패';
                        break;
                    case 'not_execution':
                        $data['result'] = '실행되지 않음';
                        break;
                    default:
                        $data['result'] = '';
                }
                $descFields = ['schedule_desc', 'target_desc', 'conditions_desc', 'executions_desc'];
                foreach($descFields as $field) {
                    if(!empty($data[$field])) {
                        $decoded = json_decode($data[$field], true);
                        if(!empty($decoded)){
                            if($field == 'executions_desc'){
                                $errorMsgs = [];
                                if(is_array($decoded)){
                                    foreach($decoded as $item) {                              
                                        if(is_array($item)){
                                            if($item['result'] == false) {
                                                $errorMsgs[] = '실패 - '.'['.$item['data']['media'].']['.$item['data']['type'].']['.$item['data']['id'].'] '.$item['data']['exec_type'].' => '.$item['data']['exec_value']." ".$item['msg'];
                                            }
                                        }else{
                                            $errorMsgs = '실패 - '.$decoded['msg'];
                                            continue;
                                        }
                                    }                          
                                    if(empty($errorMsgs)){
                                        $data[$field] = '통과';
                                    }else{
                                        $data[$field] = $errorMsgs;
                                    }
                                }
                                
                            }else{
                                if($decoded !== null) {
                                    if(isset($decoded['result']) && $decoded['result'] === true) {
                                        $data[$field] = '통과';
                                    } else{
                                        $data[$field] = '실패 - '.(isset($decoded['msg']) ? $decoded['msg'] : '');   
                                    }
                                }
                            }
                        }
                    }
                }
            }

            $result = [
                'data' => $result['data'],
            ];

            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function getLogByAdv()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'get'){
            $arg = $this->request->getGet();
            $sliceId = explode("_", $arg['id']);
            $id = $sliceId[1];
            $automations = $this->automation->getAutomationByAdv($id);
            $result = $this->automation->getLogsByAdv($arg, $id);                
            
            foreach ($result['data'] as &$data) {
                switch ($data['result']) {
                    case 'success':
                        $data['result'] = '실행됨';             
                        break;
                    case 'failed':
                        $data['result'] = '실패';
                        break;
                    case 'not_execution':
                        $data['result'] = '실행되지 않음';
                        break;
                    default:
                        $data['result'] = '';
                }
                $descFields = ['schedule_desc', 'target_desc', 'conditions_desc', 'executions_desc'];
                foreach($descFields as $field) {
                    if(!empty($data[$field])) {
                        $decoded = json_decode($data[$field], true);
                        if(!empty($decoded)){
                            if($field == 'executions_desc'){
                                $errorMsgs = [];
                                if(is_array($decoded)){
                                    foreach($decoded as $item) {                              
                                        if(is_array($item)){
                                            if($item['result'] == false) {
                                                $errorMsgs[] = '실패 - '.'['.$item['data']['media'].']['.$item['data']['type'].']['.$item['data']['id'].'] '.$item['data']['exec_type'].' => '.$item['data']['exec_value']." ".$item['msg'];
                                            }
                                        }else{
                                            $errorMsgs = '실패 - '.$decoded['msg'];
                                            continue;
                                        }
                                    }                          
                                    if(empty($errorMsgs)){
                                        $data[$field] = '통과';
                                    }else{
                                        $data[$field] = $errorMsgs;
                                    }
                                }
                                
                            }else{
                                if($decoded !== null) {
                                    if(isset($decoded['result']) && $decoded['result'] === true) {
                                        $data[$field] = '통과';
                                    } else{
                                        $data[$field] = '실패 - '.(isset($decoded['msg']) ? $decoded['msg'] : '');   
                                    }
                                }
                            }
                        }
                    }
                }
            }

            $result = [
                'data' => $result['data'],
                'automation' => $automations,
                'recordsTotal' => $result['allCount'],
                'recordsFiltered' => $result['allCount'],
                'draw' => intval($arg['draw']),
            ];

            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function createAutomation()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
            $data = $this->request->getRawInput();
            $validationResult = $this->validationData($data);
            if($validationResult['result'] != true){
                return $this->failValidationErrors($validationResult);
            }

            $mediaMapping = ['광고주' => 'company', '페이스북' => 'facebook', '구글' => 'google', '카카오' => 'kakao'];
            $typeMapping = ['광고주' => 'advertiser', '매체광고주' => 'account', '캠페인' => 'campaign', '광고그룹' => 'adgroup', '광고' => 'ad'];
            $execTypeMapping = ['상태' => 'status', '예산' => 'budget'];
            $execBudgetTypeMapping = ['원' => 'won', '%' => 'percent'];

            $data['schedule']['schedule_value'] = json_encode($data['schedule']['schedule_value']);
            $data['schedule']['exec_once'] = !empty($data['schedule']['exec_once']) ? 1 : 0;

            if(!empty($data['target'])) {
                foreach ($data['target'] as &$target) {
                    $target['media'] = $mediaMapping[$target['media']] ?? $target['media'];
                    $target['type'] = $typeMapping[$target['type']] ?? $target['type'];
                }
            }

            if(!empty($data['execution'])) {
                foreach ($data['execution'] as &$execution) {
                    $execution['media'] = $mediaMapping[$execution['media']] ?? $execution['media'];
                    $execution['type'] = $typeMapping[$execution['type']] ?? $execution['type'];
                    $execution['exec_type'] = $execTypeMapping[$execution['exec_type']] ?? $execution['exec_type'];
                    $execution['exec_budget_type'] = $execBudgetTypeMapping[$execution['exec_budget_type']] ?? $execution['exec_budget_type'];
                }
            }

            if(!empty($data['target_create_type']) && $data['target_create_type'] == 'target_seperate'){
                $seperateDatas = [];
                foreach ($data['target'] as $key => $targetData) {
                    $newItem = [
                        'schedule' => $data['schedule'],
                        'target' => [$targetData],
                        'condition' => $data['condition'],
                        'detail' => $data['detail']
                    ];
                    $newItem['detail']['subject'] = $newItem['detail']['subject']." 개별 적용 - ".$key+1;
                    foreach ($data['execution'] as $executionData) {
                        if($targetData['id'] == $executionData['id'] && $targetData['media'] == $executionData['media']){
                            $newItem['execution'] = [$executionData];
                        }
                        continue;
                    }

                    $seperateDatas[] = $newItem;
                }

                $db = \Config\Database::connect();
                $db->transStart(); 
                foreach ($seperateDatas as $seperateData) {
                    $result = $this->automation->createAutomation($seperateData);
                    if (!$result) {  // If creation fails, rollback and exit
                        $db->transRollback();
                        return false;
                    }
                }
                $result = $db->transComplete();
                return $this->respond($result);
            }

            $result = $this->automation->createAutomation($data);
            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function copyAutomation()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'post'){
            $data = $this->request->getRawInput();
            $result = $this->automation->copyAutomation($data);
            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function updateAutomation()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'put'){
            $data = $this->request->getRawInput();
            if(empty($data['seq'])){
                return $this->fail("잘못된 요청");
            }
            $validationResult = $this->validationData($data);
            if($validationResult['result'] != true){
                return $this->failValidationErrors($validationResult);
            }
            
            $mediaMapping = ['광고주' => 'company', '페이스북' => 'facebook', '구글' => 'google', '카카오' => 'kakao'];
            $typeMapping = ['광고주' => 'advertiser', '매체광고주' => 'account', '캠페인' => 'campaign', '광고그룹' => 'adgroup', '광고' => 'ad'];
            $execTypeMapping = ['상태' => 'status', '예산' => 'budget'];
            $execBudgetTypeMapping = ['원' => 'won', '%' => 'percent'];

            $data['schedule']['schedule_value'] = json_encode($data['schedule']['schedule_value']);
            $data['schedule']['exec_once'] = $data['schedule']['exec_once'] == "true" ? 1 : 0;
            if(!empty($data['target'])) {
                foreach ($data['target'] as &$target) {
                    $target['media'] = $mediaMapping[$target['media']] ?? $target['media'];
                    $target['type'] = $typeMapping[$target['type']] ?? $target['type'];
                }
            }

            if(!empty($data['execution'])) {
                foreach ($data['execution'] as &$execution) {
                    $execution['media'] = $mediaMapping[$execution['media']] ?? $execution['media'];
                    $execution['type'] = $typeMapping[$execution['type']] ?? $execution['type'];
                    $execution['exec_type'] = $execTypeMapping[$execution['exec_type']] ?? $execution['exec_type'];
                    $execution['exec_budget_type'] = $execBudgetTypeMapping[$execution['exec_budget_type']] ?? $execution['exec_budget_type'];
                }
            }

            $result = $this->automation->updateAutomation($data);
            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    public function deleteAutomation()
    {
        if($this->request->isAJAX() && strtolower($this->request->getMethod()) === 'delete'){
            $data = $this->request->getRawInput();
            
            $result = $this->automation->deleteAutomation($data);
            return $this->respond($result);
        }else{
            return $this->fail("잘못된 요청");
        }
    }

    private function validationData($data)
    {
        $validation = \Config\Services::validation();
        $validationRules      = [
            'schedule.schedule_value' => 'required',
        ];
        $validationMessages   = [
            'schedule.schedule_value' => [
                'required' => '일정을 지정해주세요.',
            ],
        ];

        $validation->setRules($validationRules, $validationMessages);
        if (!$validation->run($data)) {
            $result = [
                'result' => false,
                'msg' => $validation->getErrors(),
            ];
            return $result;
        }

        $validation->reset();

        if(!empty($data['target'])){
            foreach ($data['condition'] as $condition) {
                $validationRules      = [
                    'type' => 'required',
                    'type_value' => 'required',
                    'compare' => 'required',
                    'operation' => 'required',
                ];
                $validationMessages   = [
                    'type' => ['required' => '조건 항목은 필수 항목입니다.'],
                    'type_value' => ['required' => '조건 값은 필수 항목입니다.'],
                    'compare' => ['required' => '일치여부는 필수 항목입니다.'],
                    'operation' => ['required' => '연산조건은 필수 항목입니다.'],
                ];

                $validation->setRules($validationRules, $validationMessages);
                if (!$validation->run($condition)) {
                    $result = [
                        'result' => false,
                        'msg' => $validation->getErrors(),
                    ];
                    return $result;
                }
            }
            $validation->reset();
        }

        if(empty($data['execution'])){
            $validationRules['execution'] = 'required';
            $validationMessages['execution'] = ['required' => '실행항목을 추가해주세요.'];
        }else{
            foreach ($data['execution'] as $execution) {
                $validationRules      = [
                    'order' => 'required',
                    'exec_type' => 'required',
                    'exec_value' => 'required',
                ];
                $validationMessages   = [
                    'order' => ['required' => '실행순서는 필수 항목입니다.'],
                    'exec_type' => ['required' => '실행항목은 필수 항목입니다.'],
                    'exec_value' => ['required' => '세부항목은 필수 항목입니다.'],
                ];
    
                if($execution['exec_type'] == '예산'){
                    $validationRules['exec_budget_type'] = 'required';
                    $validationMessages['exec_budget_type'] = ['required' => '단위는 필수 항목입니다.'];
                }

                $validation->setRules($validationRules, $validationMessages);
                if (!$validation->run($execution)) {
                    $result = [
                        'result' => false,
                        'msg' => $validation->getErrors(),
                    ];
                    return $result;
                }
            }
        }

        $validation->reset();

        $validationRules      = ['detail.subject' => 'required'];
        $validationMessages   = ['detail.subject' => ['required' => '제목은 필수 항목입니다.']];
        $validation->setRules($validationRules, $validationMessages);
        if (!$validation->run($data)) {
            $result = [
                'result' => false,
                'msg' => $validation->getErrors(),
            ];
            return $result;
        }

        return ['result' => true];
    }

    public function automation()
    {
        CLI::write("자동화를 실행합니다.", "light_red");
        $automations = $this->automation->getAutomations();
        $seqs = [];
        $logs = [];
        $step = 1;
        $total = count($automations);
        foreach ($automations as $automation) {
            $result = [];
            //if($automation['aa_seq'] != '202'){continue;}
            if(!empty($automation)){
                $schedulePassData = $this->checkAutomationSchedule($automation);           
                $result['schedule'] = $schedulePassData;
                
                if(!empty($schedulePassData['result'])){
                    $targets = $this->automation->getAutomationTargets($automation['aa_seq']);  
                    if(!empty($targets)){
                        $checkTargets = [];
                        foreach ($targets as $target) {
                            $targetData = $this->checkAutomationTarget($target);
                            if($targetData['result'] == false){
                                continue;
                            }
                            $checkTargets[] = $targetData['target'];
                        }

                        $targetDatas = $this->setData($checkTargets);  
                        if(empty($targetDatas)){
                            $resultRow = $this->recordResult([
                                'seq' => $automation['aa_seq'],
                                'status'=> 'not_execution'
                            ]);
                            $resultTarget = [
                                'result' => false,
                                'msg' => '비교 대상 데이터가 존재하지 않습니다.',
                                'seq' => $automation['aa_seq'],
                            ];
                            $result['target'] = $resultTarget;
                            if(!empty($resultRow)){
                                $this->recordLog($result, $resultRow);
                            }
                            continue;
                        }else{
                            $resultTarget = [
                                'result' => true,
                                'msg' => '대상이 일치합니다.',
                                'seq' => $automation['aa_seq'],
                                'target' => $targetDatas,
                            ];
                            $result['target'] = $resultTarget;
                        }

                        if(!empty($targetDatas)){
                            $conditionPassData = $this->checkAutomationCondition($targetDatas, $automation['aa_seq']);
                            $result['conditions'] = $conditionPassData;
                            if($conditionPassData['result'] == false){
                                $resultRow = $this->recordResult($conditionPassData);
                                if(!empty($resultRow)){
                                    $this->recordLog($result, $resultRow);
                                }
                                continue;
                            }
                            $seqs[] = $conditionPassData['seq'];
                            $logs[] = $result;
                        }
                    }else{
                        $seqs[] = $schedulePassData['seq'];
                        $logs[] = $result;
                    }
                }
            }
        }

        if(!empty($seqs)){
            $executionData = [];
            foreach ($seqs as $seq) {
                CLI::showProgress($step++, $total);
                $executionData[] = $this->automationExecution($seq);
            }

            foreach ($executionData as $exec) {
                $resultRow = $this->recordResult($exec['result']);
                if(!empty($resultRow)){
                    foreach ($logs as &$log) {
                        if($log['schedule']['seq'] === $exec['result']['seq']){
                            $log['executions'] = $exec['log'];
                            $this->recordLog($log, $resultRow);
                        }
                    }
                }
            }

            foreach ($executionData as $exec) {
                if($exec['result'] == true){
                    $automation = $this->automation->getAutomationBySeq($exec['result']['seq']);
                    if(!empty($automation['aa_slack_webhook']) && !empty($automation['aa_slack_msg'])){
                        $slackChat = new SlackChat;
                        $slackChat->sendWebHookMessage($automation['aa_slack_webhook'], $automation['aa_slack_msg']);
                    }
                }
            }
        }

        CLI::write("자동화 실행 완료", "light_red");
    }

    public function checkAutomationSchedule($automation)
    {
        $resultArray = [
            'result' => false,
            'status' => 'not_execution',
            'msg' => '설정 시간 일치하지 않음',
            'seq' => $automation['aa_seq'],
        ];

        $currentDate = new Time('now');
        $currentDay = $currentDate->format('N');
        $currentTime = $currentDate->toTimeString();
        $schedule = $this->convertJsonToTimes($automation['aas_schedule_value']);

        if (array_key_exists($currentDay, $schedule)) {
            if (!empty($automation['aas_exec_once']) && !empty($automation['aar_exec_timestamp_success'])) {
                $execTimestampSuccess = Time::parse($automation['aar_exec_timestamp_success']);
                if ($execTimestampSuccess->toDateString() === $currentDate->toDateString()) {
                    return $resultArray;
                }
            }

            foreach ($schedule[$currentDay] as $time) {
                $startTime = Time::parse($time);
                $endTime = $startTime->addMinutes(30);
                $now = Time::parse($currentTime);
                if ($now->isAfter($startTime) && $now->isBefore($endTime)) {
                    $resultArray = [
                        'result' => true,
                        'status' => 'success',
                        'msg' => '설정 시간 일치',
                        'seq' => $automation['aa_seq'],
                    ];
                    return $resultArray;
                }
            }
        }

        return $resultArray;
    }

    public function checkAutomationTarget($target)
    {
        $types = ['advertiser', 'account', 'campaign', 'adgroup', 'ad'];
        $mediaTypes = ['company', 'facebook', 'google', 'kakao'];
        //값 별로 메소드 매칭
        if (in_array($target['aat_type'], $types) && in_array($target['aat_media'], $mediaTypes)) {
            $methodName = "getTarget" . ucfirst($target['aat_media']);
            if (method_exists($this->automation, $methodName)) {
                $data = $this->automation->$methodName($target);
                if(empty($data)){
                    return ['result' => false];
                }
                $data = $this->sumData($data);
                return  [
                    'result' => true,
                    'seq' => $target['aat_idx'],
                    'target' => $data,
                ];
            }
        }
    }

    public function checkAutomationCondition($targetData, $seq)
    {
        $types = ['status', 'budget', 'dbcost', 'unique_total', 'spend', 'margin', 'margin_rate', 'sales', 'conversion'];
        $conditions = $this->automation->getAutomationConditionBySeq($seq);
        if(empty($conditions)){
            return [            
                "result" => false,
                'status' => 'failed',
                "msg" => '조건이 존재하지 않음',
                "seq" => $seq,
            ];
        }

        $isTargetMatched = false;
        $allConditionsMatched = true;
        $operation = $conditions[0]['operation'];
        foreach ($conditions as $condition) {       
            $conditionMatched = false;       
            $message = "일치하는 조건이 없습니다.";
            if ($condition['type'] === 'status') {//status 비교
                if ($targetData['status'] == $condition['type_value']) {
                    $conditionMatched = true;
                    $message = 'status 일치';
                }else{
                    $message = 'status가 일치하지 않습니다.';
                }
            }else{//그 외 필드 비교
                foreach ($types as $type) {                     
                    if ($condition['type'] === $type) {
                        switch ($condition['compare']) {
                            case 'less':
                                $conditionMatched = $targetData[$type] < $condition['type_value'];
                                $message = $conditionMatched ? $type." ".$condition['compare'].' 조건 일치' : $type.'값이 조건값보다 큽니다.'."(".$condition['compare'].")";
                                break;
                            case 'greater':
                                $conditionMatched = $targetData[$type] > $condition['type_value'];
                                $message = $conditionMatched ? $type." ".$condition['compare'].' 조건 일치' : $type.'값이 조건값보다 작습니다.'."(".$condition['compare'].")";
                                break;
                            case 'less_equal':
                                $conditionMatched = $targetData[$type] <= $condition['type_value'];
                                $message = $conditionMatched ? $type." ".$condition['compare'].' 조건 일치' : $type.'값이 조건값보다 크거나 같지 않습니다.'."(".$condition['compare'].")";
                                break;
                            case 'greater_equal':
                                $conditionMatched = $targetData[$type] >= $condition['type_value'];
                                $message = $conditionMatched ? $type." ".$condition['compare'].' 조건 일치' : $type.'값이 조건값보다 작거나 같지 않습니다.'."(".$condition['compare'].")";
                                break;
                            case 'equal':
                                $conditionMatched = $targetData[$type] == $condition['type_value'];
                                $message = $conditionMatched ? $type." ".$condition['compare'].' 조건 일치' : $type.'값이 조건값과 일치하지 않습니다.'."(".$condition['compare'].")";
                                break;
                            case 'not_equal':
                                $conditionMatched = $targetData[$type] != $condition['type_value'];
                                $message = $conditionMatched ? $type." ".$condition['compare'].' 조건 일치' : $type.'값이 조건값과 같습니다.'."(".$condition['compare'].")";
                                break;
                            default:
                                $conditionMatched = false;
                                break;
                        }
                    }
                }
            }
            
            if($operation == 'or'){
                if($conditionMatched){
                    $isTargetMatched = true;
                    break;
                }
            }

            if($operation == 'and'){
                if (!$conditionMatched) {
                    $allConditionsMatched = false;
                    break;
                }
            }
        }
        
        if(($operation == 'or' && $isTargetMatched) || ($operation == 'and' && $allConditionsMatched)){
            return [            
                "result" => true,
                'status' => 'success',
                "msg" => $message,
                "seq" => $seq,
            ];
        }else{
            return [
                "result" => false,
                'status' => 'not_execution',
                "msg" => $message,
                "seq" => $seq,
            ];
        }
    }
    
    public function automationExecution($seq)
    {
        $executions = $this->automation->getExecution($seq);

        if(empty($executions)){
            return [            
                "result" => false,
                'status' => 'failed',
                "msg" => '실행항목이 존재하지 않음',
                "seq" => $seq,
            ];
        }
        
        $originalSettings = [];
        $result = [
            'result' => [],
            'log' => [],
        ];
        try {
            foreach ($executions as $execution) {
                $zenith = null;
                switch ($execution['media']) {
                    case 'facebook':
                        $zenith = new ZenithFB();
                        break;
                    case 'google':
                        $zenith = new ZenithGG();
                        break;
                    case 'kakao':
                        $zenith = new ZenithKM();
                        break;
                    default:
                        break;
                }
                if($zenith){ 
                    switch ($execution['type']) {
                        case 'campaign':
                            $customerId = null;
                            if ($execution['media'] === 'google') {
                                $customerId = $this->google->getCustomerById($execution['id'], 'campaign');
                            }
                            switch ($execution['exec_type']) {
                                case 'status':
                                    if ($execution['media'] === 'facebook') {
                                        if($execution['exec_value'] === "ON"){
                                            $status = 'ACTIVE';
                                        }else{
                                            $status = 'PAUSED';
                                        }
                                        $originalData = $zenith->getCampaignStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->setCampaignStatus($execution['id'], $status);
                                        }                                  
                                    } else if ($execution['media'] === 'google') {
                                        if($execution['exec_value'] === "ON"){
                                            $status = ['status' => 'ENABLED'];
                                        }else{
                                            $status = ['status' => 'PAUSED'];
                                        }
                                        $originalData = $zenith->getCampaignStatusBudget($customerId['customerId'], $execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->updateCampaign($customerId['customerId'], $execution['id'], $status);
                                        }else{
                                            $return = false;
                                        }
                                    } else if ($execution['media'] === 'kakao') {
                                        $originalData = $zenith->getCampaignStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->setCampaignOnOff($execution['id'], $execution['exec_value']);
                                            if(isset($return['http_code'])){
                                                if($return['http_code'] == 200){
                                                    $return = true;
                                                }else{
                                                    throw new Exception("카카오 캠페인 상태 수정 오류 발생.");
                                                }
                                            }else{
                                                throw new Exception("카카오 캠페인 상태 수정 오류 발생.");
                                            }
                                        }else{
                                            $return = false;
                                        }
                                    }
                                    break;
                                case 'budget':     
                                    if ($execution['media'] === 'facebook') {
                                        $originalData = $zenith->getCampaignStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'budget' => $originalData['budget'] ?? 0,
                                            ];

                                            if ($execution['exec_budget_type'] == 'percent') {
                                                $adjustedBudget = ($originalData['budget']) * (1 + ($execution['exec_value'] / 100));
                                                $adjustedBudget = round($adjustedBudget);
                                            } else {
                                                $adjustedBudget = $execution['exec_value'];
                                            }

                                            $data = [
                                                'id' => $execution['id'],
                                                'budget' => $adjustedBudget
                                            ];
                                            $return = $zenith->updateCampaignBudget($data);
                                        }else{
                                            $return = false;
                                        }  
                                    } else if ($execution['media'] === 'google') {
                                        $originalData = $zenith->getCampaignStatusBudget($customerId['customerId'], $execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'budget' => $originalData['budget'] ?? 0,
                                            ];

                                            if ($execution['exec_budget_type'] == 'percent') {
                                                $adjustedBudget = ($originalData['budget']) * (1 + ($execution['exec_value'] / 100));
                                                $adjustedBudget = round($adjustedBudget);
                                            } else {
                                                $adjustedBudget = $execution['exec_value'];
                                            }

                                            $return = $zenith->updateCampaignBudget($customerId['customerId'], $execution['id'], ['budget' => $adjustedBudget]);
                                        }else{
                                            $return = false;
                                        }
                                    } else if ($execution['media'] === 'kakao') {
                                        $originalData = $zenith->getCampaignStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'budget' => $originalData['budget'] ?? 0,
                                            ];

                                            if ($execution['exec_budget_type'] == 'percent') {
                                                $adjustedBudget = ($originalData['budget']) * (1 + ($execution['exec_value'] / 100));
                                                $adjustedBudget = round($adjustedBudget);
                                            } else {
                                                $adjustedBudget = $execution['exec_value'];
                                            }

                                            $data = [
                                                'type' => 'campaign',
                                                'id' => $execution['id'],
                                                'budget' => $adjustedBudget
                                            ];
                                            $return = $zenith->setDailyBudgetAmount($data);
                                            if(isset($return['code']) && isset($return['msg'])){
                                                throw new Exception($return['msg']);
                                            }else{
                                                $return = true;                 
                                            }
                                        }else{
                                            $return = false;
                                        }
                                    }
                                    break;
                                default:
                                    break;
                            }
                            break;
                        case 'adgroup':
                            $customerId = null;
                            if ($execution['media'] === 'google') {
                                $customerId = $this->google->getCustomerById($execution['id'], 'adgroup');
                            }
                            switch ($execution['exec_type']) {
                                case 'status':
                                    if ($execution['media'] === 'facebook') {
                                        if($execution['exec_value'] === "ON"){
                                            $status = 'ACTIVE';
                                        }else{
                                            $status = 'PAUSED';
                                        }
                                        $originalData = $zenith->getAdsetStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->setAdsetStatus($execution['id'], $status);
                                        }else{
                                            $return = false;
                                        }  
                                    } else if ($execution['media'] === 'google') {
                                        if($execution['exec_value'] === "ON"){
                                            $status = ['status' => 'ENABLED'];
                                        }else{
                                            $status = ['status' => 'PAUSED'];
                                        }
                                        $originalData = $zenith->getAdgroupStatus($customerId['customerId'], $execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->updateAdGroup($customerId['customerId'], $execution['id'], $status);
                                        }else{
                                            $return = false;
                                        }
                                    } else if ($execution['media'] === 'kakao') {
                                        $originalData = $zenith->getAdgroupStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->setAdGroupOnOff($execution['id'], $execution['exec_value']);
                                            if(isset($return['http_code'])){
                                                if($return['http_code'] == 200){
                                                    $return = true;
                                                }else{
                                                    throw new Exception("카카오 광고그룹 상태 수정 오류 발생.");
                                                }
                                            }else{
                                                throw new Exception("카카오 광고그룹 상태 수정 오류 발생.");
                                            }
                                        }else{
                                            $return = false;
                                        }
                                    }
                                    break;
                                case 'budget':
                                    if ($execution['media'] === 'facebook') {
                                        $originalData = $zenith->getAdsetStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'budget' => $originalData['budget'] ?? 0,
                                            ];
                                            
                                            if ($execution['exec_budget_type'] == 'percent') {
                                                $adjustedBudget = ($originalData['budget']) * (1 + ($execution['exec_value'] / 100));
                                                $adjustedBudget = round($adjustedBudget);
                                            } else {
                                                $adjustedBudget = $execution['exec_value'];
                                            }

                                            $data = [
                                                'id' => $execution['id'],
                                                'budget' => $adjustedBudget
                                            ];
                                            $return = $zenith->updateAdSetBudget($data);
                                        }else{
                                            $return = false;
                                        }  
                                    } else if ($execution['media'] === 'kakao') {
                                        $originalData = $zenith->getAdgroupStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'budget' => $originalData['budget'] ?? 0,
                                            ];

                                            if ($execution['exec_budget_type'] == 'percent') {
                                                $adjustedBudget = ($originalData['budget']) * (1 + ($execution['exec_value'] / 100));
                                                $adjustedBudget = round($adjustedBudget);
                                            } else {
                                                $adjustedBudget = $execution['exec_value'];
                                            }

                                            $data = [
                                                'type' => 'adgroup',
                                                'id' => $execution['id'],
                                                'budget' => $adjustedBudget
                                            ];
                                            $return = $zenith->setDailyBudgetAmount($data);
                                            if(isset($return['code']) && isset($return['msg'])){
                                                throw new Exception($return['msg']);
                                            }else{
                                                $return = true;                 
                                            }
                                        }else{
                                            $return = false;
                                        }
                                    }
                                    break;
                                default:
                                    break;
                            }
                            break;
                        case 'ad':
                            $customerId = null;                               
                            if ($execution['media'] === 'google') {
                                $customerId = $this->google->getCustomerById($execution['id'], 'ad');
                            }
                            switch ($execution['exec_type']) {
                                case 'status':
                                    if ($execution['media'] === 'facebook') {
                                        if($execution['exec_value'] === "ON"){
                                            $status = 'ACTIVE';
                                        }else{
                                            $status = 'PAUSED';
                                        }
                                        $originalData = $zenith->getAdStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->setAdStatus($execution['id'], $status);
                                        }else{
                                            $return = false;
                                        } 
                                    } else if ($execution['media'] === 'google') {
                                        if($execution['exec_value'] === "ON"){
                                            $status = ['status' => 'ENABLED'];
                                        }else{
                                            $status = ['status' => 'PAUSED'];
                                        }                                     
                                        $originalData = $zenith->getAdStatus($customerId['customerId'], $execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->updateAdGroupAd($customerId['customerId'], null, $execution['id'], $status);
                                        }else{
                                            $return = false;
                                        }
                                    } else if ($execution['media'] === 'kakao') {
                                        $originalData = $zenith->getAdStatusBudget($execution['id']);
                                        if(!empty($originalData)){
                                            $originalSettings[] = [
                                                'media' => $execution['media'],
                                                'type' => $execution['type'],
                                                'id' => $execution['id'],
                                                'status' => $originalData['status'],
                                            ];
                                            $return = $zenith->setCreativeOnOff($execution['id'], $execution['exec_value']);
                                            if(isset($return['http_code'])){
                                                if($return['http_code'] == 200){
                                                    $return = true;
                                                }else{
                                                    throw new Exception("카카오 광고그룹 상태 수정 오류 발생.");
                                                }
                                            }else{
                                                throw new Exception("카카오 광고그룹 상태 수정 오류 발생.");
                                            }
                                        }else{
                                            $return = false;
                                        } 
                                    }
                                    break;
                            }
                            break;
                        default:
                            break;
                    }
                    if(!empty($return)){
                        $logData = [
                            'media' => $execution['media'],
                            'id' => $execution['id'],
                            'type' => $execution['type'],
                            'change_type' => $execution['exec_type'] == 'status' ? 'status' : 'budget',
                            'old_value' => '',
                            'change_value' => $execution['exec_value'],
                            'nickname' => '자동화',
                        ];
                
                        $logger = new AdvLoggerService();
                        $logger->insertLog($logData);

                        $result['log'][] = [
                            "result" => true,
                            'status' => 'success',
                            "msg" => '실행 완료',
                            "seq" => $seq,
                            "data" => [
                                'media' => $execution['media'],
                                'type' => $execution['type'],
                                'id' => $execution['id'],
                                'exec_type' => $execution['exec_type'],
                                'exec_value' => $execution['exec_value'],
                            ]
                        ];
                    }else{
                        throw new Exception("Api 오류 발생.");
                    }
                }
            }
            $result['result'] = [
                "result" => true,
                'status' => 'success',
                "seq" => $seq,
            ];
            return $result;
        } catch (Exception $e) {
            foreach ($originalSettings as $original) {
                switch ($original['media']) {
                    case 'facebook':
                        $zenith = new ZenithFB();
                        break;
                    case 'google':
                        $zenith = new ZenithGG();
                        break;
                    case 'kakao':
                        $zenith = new ZenithKM();
                        break;
                    default:
                        break;
                }
                
                switch ($original['type']) {
                    case 'campaign':
                        $customerId = null;
                        if ($original['media'] === 'google') {
                            $customerId = $this->google->getCustomerById($original['id'], 'campaign');
                        }

                        if(isset($original['status'])){
                            if ($original['media'] === 'facebook') {
                                $zenith->setCampaignStatus($original['id'], $original['status']);                            
                            } else if ($original['media'] === 'google') {
                                $zenith->updateCampaign($customerId['customerId'], $original['id'], $original['status']);
                            } else if ($original['media'] === 'kakao') {
                                $zenith->setCampaignOnOff($original['id'], $original['status']);
                            }
                        }

                        if(isset($original['budget'])){
                            if ($original['media'] === 'facebook') {
                                $data = [
                                    'id' => $original['id'],
                                    'budget' => $original['budget']
                                ];
                                $zenith->updateCampaignBudget($data); 
                            } else if ($original['media'] === 'google') {
                                $zenith->updateCampaignBudget($customerId['customerId'], $original['id'], ['budget' => $original['budget']]);
                            } else if ($original['media'] === 'kakao') {
                                $data = [
                                    'type' => 'campaign',
                                    'id' => $original['id'],
                                    'budget' => $original['budget']
                                ];
                                $zenith->setDailyBudgetAmount($data);
                            }
                        }
                        break;
                    case 'adgroup':
                        $customerId = null;
                        if ($original['media'] === 'google') {
                            $customerId = $this->google->getCustomerById($original['id'], 'adgroup');
                        }

                        if(isset($original['status'])){
                            if ($original['media'] === 'facebook') {
                                $zenith->setAdsetStatus($original['id'], $original['status']);                         
                            } else if ($original['media'] === 'google') {
                                $zenith->updateAdGroup($customerId['customerId'], $original['id'], $original['status']);
                            } else if ($original['media'] === 'kakao') {
                                $zenith->setAdGroupOnOff($original['id'], $original['status']);
                            }
                        }

                        if(isset($original['budget'])){
                            if ($original['media'] === 'facebook') {
                                $data = [
                                    'id' => $original['id'],
                                    'budget' => $original['budget']
                                ];
                                $zenith->updateAdSetBudget($data);
                            } else if ($original['media'] === 'kakao') {
                                $data = [
                                    'type' => 'adgroup',
                                    'id' => $original['id'],
                                    'budget' => $original['budget']
                                ];
                                $zenith->setDailyBudgetAmount($data);
                            }
                        }
                        break;
                    case 'ad':
                        $customerId = null;                               
                        if ($original['media'] === 'google') {
                            $customerId = $this->google->getCustomerById($original['id'], 'ad');
                        }

                        if(isset($original['status'])){
                            if ($original['media'] === 'facebook') {
                                $zenith->setAdStatus($original['id'], $original['status']);                        
                            } else if ($original['media'] === 'google') {
                                $zenith->updateAdGroupAd($customerId['customerId'], null, $original['id'], $original['status']);
                            } else if ($original['media'] === 'kakao') {
                                $zenith->setCreativeOnOff($original['id'], $original['status']);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }

            $result['result'] = [
                "result" => false,
                'status' => 'failed',
                "seq" => $seq
            ];

            $result['log'] = [
                "result" => false,
                'status' => 'failed',
                'msg' => $e->getMessage(),
                "seq" => $seq,
            ];
            return $result;
        }
    }
    
    /* public function checkAutomationCondition($target)
    {
        $types = ['budget', 'dbcost', 'dbcount', 'cost', 'margin', 'margin_rate', 'sale', 'impression', 'click', 'cpc', 'ctr', 'conversion'];
        $conditions = $this->automation->getAutomationConditionBySeq($target['aa_seq']);
        if(empty($conditions)){return false;}
        //순서 재정렬
        usort($conditions, function($a, $b) {
            return $a['order'] - $b['order'];
        });

        $isTargetMatched = false;
        $allConditionsMatched = true;
        foreach ($conditions as $condition) {       
            $conditionMatched = false;       
            $message = "일치하는 조건이 존재하지 않습니다.";
            if ($condition['type'] === 'status') {//status 비교
                if ($target['status'] == $condition['type_value']) {
                    $conditionMatched = true;
                    $message = 'status 일치';
                }else{
                    $message = 'status가 일치하지 않습니다.';
                }
            }else{//그 외 필드 비교
                foreach ($types as $type) {                     
                    if ($condition['type'] === $type) {
                        switch ($condition['compare']) {
                            case 'less':
                                $conditionMatched = $target[$type] < $condition['type_value'];
                                $message = $conditionMatched ? $condition['compare'].' 조건 일치' : $type.'값이 조건값보다 큽니다.'."(".$condition['compare'].")";;
                                break;
                            case 'greater':
                                $conditionMatched = $target[$type] > $condition['type_value'];
                                $message = $conditionMatched ? $condition['compare'].' 조건 일치' : $type.'값이 조건값보다 작습니다.'."(".$condition['compare'].")";;
                                break;
                            case 'less_equal':
                                $conditionMatched = $target[$type] <= $condition['type_value'];
                                $message = $conditionMatched ? $condition['compare'].' 조건 일치' : $type.'값이 조건값보다 크거나 같지 않습니다.'."(".$condition['compare'].")";;
                                break;
                            case 'greater_equal':
                                $conditionMatched = $target[$type] >= $condition['type_value'];
                                $message = $conditionMatched ? $condition['compare'].' 조건 일치' : $type.'값이 조건값보다 작거나 같지 않습니다.'."(".$condition['compare'].")";;
                                break;
                            case 'equal':
                                $conditionMatched = $target[$type] == $condition['type_value'];
                                $message = $conditionMatched ? $condition['compare'].' 조건 일치' : $type.'값이 조건값과 일치하지 않습니다.'."(".$condition['compare'].")";;
                                break;
                            case 'not_equal':
                                $conditionMatched = $target[$type] != $condition['type_value'];
                                $message = $conditionMatched ? $condition['compare'].' 조건 일치' : $type.'값이 조건값과 같습니다.'."(".$condition['compare'].")";
                                break;
                            default:
                                $conditionMatched = false;
                                $message = '비교할 조건이 존재하지 않습니다.';
                                break;
                        }
                    }
                }
            }

            if($condition['operation'] == 'or'){
                if($conditionMatched){
                    $isTargetMatched = true;
                    break;
                }else{
                    //조건이 하나이고 조건에 해당되지 않을때
                    if(count($conditions) == 1){
                        $allConditionsMatched = false; 
                    }

                    //and 조건이 없을때
                    if (!in_array('and', array_column($conditions, 'operation'))) {
                        $allConditionsMatched = false; 
                    }
                }
            }

            if($condition['operation'] == 'and'){
                if(!$conditionMatched){
                    $allConditionsMatched = false; 
                    //뒤에 or 조건이 있을수 있어서 or 조건이 없을때만 break
                    $nextKey = array_search($condition, $conditions) + 1;
                    if ($nextKey < count($conditions)) {
                        if ($conditions[$nextKey]['operation'] != 'or') {
                            break;
                        }
                    } else {
                        break;
                    }
                }
            }
            
        }

        if($isTargetMatched || $allConditionsMatched){
            $matchedArray['match'][] = [
                'aa_seq' => $target['aa_seq'],
                'msg' => $message
            ];
        }else{
            $matchedArray['notMatch'][] = [
                'aa_seq' => $target['aa_seq'],
                'msg' => $message
            ];
        }

    return $matchedArray;
    } */

    private function sumData($data)
    {
        $formatData = [];
        $formatData['budget'] = $formatData['click'] = $formatData['spend'] = $formatData['sales'] = $formatData['unique_total'] = $formatData['margin'] = 0;
        if(isset($data[0]['status']) && in_array($data[0]['status'], ['ON', '1', 'ACTIVE', 'ENABLED'])){
            $formatData['status'] = 'ON';
        }else{
            $formatData['status'] = 'OFF';
        }
        foreach ($data as $d) {            
            $formatData['budget'] += $d['budget'];
            //$formatData['impressions'] += $d['impressions'];
            $formatData['click'] += $d['click'];
            $formatData['spend'] += $d['spend'];
            $formatData['sales'] += $d['sales'];
            $formatData['unique_total'] += $d['unique_total'];
            $formatData['margin'] += $d['margin'];
        }

        return $formatData;
    }

    private function setData($data)
    {
        $formatData = [];
        $formatData['budget'] = $formatData['click'] = $formatData['spend'] = $formatData['sales'] = $formatData['unique_total'] = $formatData['margin'] = $formatData['dbcost'] = $formatData['conversion']= $formatData['margin_rate'] = 0;
        if(isset($data[0]['status']) && in_array($data[0]['status'], ['ON', '1', 'ACTIVE', 'ENABLED'])){
            $formatData['status'] = 'ON';
        }else{
            $formatData['status'] = 'OFF';
        }
        foreach ($data as $d) {            
            $formatData['budget'] += $d['budget'];
            //$formatData['impressions'] += $d['impressions'];
            $formatData['click'] += $d['click'];
            $formatData['spend'] += $d['spend'];
            $formatData['sales'] += $d['sales'];
            $formatData['unique_total'] += $d['unique_total'];
            $formatData['margin'] += $d['margin'];

            //CPC(Cost Per Click: 클릭당단가 (1회 클릭당 비용)) = 지출액/링크클릭
            /* if($formatData['click'] > 0){
                $formatData['cpc'] = round($formatData['spend'] / $formatData['click']);
            } */

            //CTR(Click Through Rate: 클릭율 (노출 대비 클릭한 비율)) = (링크클릭/노출수)*100
            
            /* if($formatData['impressions'] > 0){
                $formatData['ctr'] = ($formatData['click'] / $formatData['impressions']) * 100;
            } */

            //CPA(Cost Per Action: 현재 DB단가(전환당 비용)) = 지출액/유효db
            if($formatData['unique_total'] > 0){
                $formatData['dbcost'] = round($formatData['spend'] / $formatData['unique_total']);
            }

            //CVR(Conversion Rate:전환율 = (유효db / 링크클릭)*100
            if ($formatData['click'] > 0) {
                $formatData['conversion'] = ($formatData['unique_total'] / $formatData['click']) * 100;
            }

            //수익률 = (수익/매출액)*100
            if ($formatData['sales'] > 0) {
                $formatData['margin_rate'] = round(($formatData['margin'] / $formatData['sales']) * 100);
            } else {
                $formatData['margin_rate'] = 0;
            } 
        }

        return $formatData;
    }

    private function recordResult($result)
    {
        $resultData = [
            'idx' => $result['seq'],
            'result' => $result['status'],
            'exec_timestamp' => date('Y-m-d H:i:s')
        ];

        $row = $this->automation->recodeResult($resultData);
        return $row;
    }

    private function recordLog($log, $resultRow)
    {
        $data = [];
        if(!empty($log['schedule'])){
            $data['idx'] = $resultRow['seq'];
            $data['reg_datetime'] = $resultRow['reg_datetime'];
            $data['schedule_desc'] = json_encode($log['schedule'], JSON_UNESCAPED_UNICODE);
        }

        if(isset($log['target'])) {
            $data['idx'] = $resultRow['seq'];
            $data['reg_datetime'] = $resultRow['reg_datetime'];
            $data['target_desc'] = json_encode($log['target'], JSON_UNESCAPED_UNICODE);
        }

        if(isset($log['conditions'])) {
            $data['idx'] = $resultRow['seq'];
            $data['reg_datetime'] = $resultRow['reg_datetime'];
            $data['conditions_desc'] = json_encode($log['conditions'], JSON_UNESCAPED_UNICODE);
        }

        if(isset($log['executions'])) {
            $data['reg_datetime'] = $resultRow['reg_datetime'];
            $data['executions_desc'] = json_encode($log['executions'], JSON_UNESCAPED_UNICODE);
        }

        if(!empty($data)){
            $this->automation->recodeLog($data);
        }
    }

    private function convertJsonToTimes($json) {
        $data = json_decode($json, true);
        $convertedTimes = [];
        foreach ($data as $key => $times) {
            foreach ($times as $time) {
                // 값을 2로 나누어 시간으로 변환
                $hour = floor($time / 2);
                $minute = ($time % 2) * 30;
                
                $convertedTime = sprintf("%d:%02d", $hour, $minute);
                $convertedTimes[$key][] = $convertedTime;
            }
        }

        return $convertedTimes;
    }
}
