<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;

class QuantumSeeder extends Seeder
{
    public function run()
    {
        $now = date('Y-m-d H:i:s');

        $organizationId = $this->upsertOrganization($now);
        $userIds = $this->seedDemoUsers($organizationId, $now);
        $siteId = $this->upsertSite($organizationId, $now);

        $turbineOneId = $this->upsertTurbine($siteId, [
            'turbine_code' => 'QTM-TUR-001',
            'name' => 'Turbine 01',
            'manufacturer' => 'Vestas',
            'model' => 'V136-4.2MW',
            'serial_number' => 'V136-PT-001',
            'rated_power_kw' => 4200.00,
            'hub_height_m' => 112.00,
            'rotor_diameter_m' => 136.00,
            'commissioned_at' => '2024-05-10',
            'status' => 'active',
        ], $now);

        $this->upsertTurbine($siteId, [
            'turbine_code' => 'QTM-TUR-002',
            'name' => 'Turbine 02',
            'manufacturer' => 'Siemens Gamesa',
            'model' => 'SG 5.0-145',
            'serial_number' => 'SG-PT-002',
            'rated_power_kw' => 5000.00,
            'hub_height_m' => 105.00,
            'rotor_diameter_m' => 145.00,
            'commissioned_at' => '2024-06-14',
            'status' => 'active',
        ], $now);

        $taskIds = [
            'inspection' => $this->upsertTask($organizationId, [
                'task_code' => 'INSPECT-GEARBOX',
                'name' => 'Inspect gearbox assembly',
                'description' => 'Visual inspection, oil leak check, and temperature anomaly review.',
                'category' => 'mechanical',
                'estimated_duration_minutes' => 90,
                'requires_evidence' => 1,
                'status' => 'active',
            ], $now),
            'blade' => $this->upsertTask($organizationId, [
                'task_code' => 'BLADE-EDGE-CHECK',
                'name' => 'Check blade leading edge',
                'description' => 'Inspect erosion points, lightning protection, and visible structural defects.',
                'category' => 'blade',
                'estimated_duration_minutes' => 120,
                'requires_evidence' => 1,
                'status' => 'active',
            ], $now),
            'torque' => $this->upsertTask($organizationId, [
                'task_code' => 'TORQUE-BOLT-VERIFY',
                'name' => 'Verify tower bolt torque',
                'description' => 'Confirm torque values against the preventive maintenance baseline.',
                'category' => 'structural',
                'estimated_duration_minutes' => 60,
                'requires_evidence' => 0,
                'status' => 'active',
            ], $now),
        ];

        $interventionId = $this->upsertIntervention($organizationId, $siteId, $turbineOneId, [
            'intervention_code' => 'MI-2026-0001',
            'title' => 'Quarterly preventive maintenance',
            'description' => 'Scheduled inspection and maintenance cycle for gearbox, blades, and structural fasteners.',
            'intervention_type' => 'preventive',
            'maintenance_mode' => 'scheduled',
            'priority' => 'medium',
            'status' => 'completed',
            'reported_at' => '2026-03-22 08:00:00',
            'scheduled_start_at' => '2026-03-24 09:00:00',
            'scheduled_end_at' => '2026-03-24 13:00:00',
            'started_at' => '2026-03-24 09:15:00',
            'completed_at' => '2026-03-24 12:45:00',
            'created_by_user_id' => $userIds['owner'],
            'assigned_to_user_id' => $userIds['manager'],
            'external_reference' => 'CMMS-QTM-240324-01',
        ], $now);

        $interventionTaskIds = [
            $this->upsertInterventionTask($interventionId, $taskIds['inspection'], [
                'sequence_no' => 1,
                'task_label' => 'Inspect gearbox assembly',
                'task_description_snapshot' => 'Visual inspection, oil leak check, and temperature anomaly review.',
                'status' => 'completed',
                'notes' => 'No oil leakage detected. Thermal readings within expected range.',
                'performed_by_user_id' => $userIds['manager'],
                'due_at' => '2026-03-24 10:00:00',
                'completed_at' => '2026-03-24 09:58:00',
            ], $now),
            $this->upsertInterventionTask($interventionId, $taskIds['blade'], [
                'sequence_no' => 2,
                'task_label' => 'Check blade leading edge',
                'task_description_snapshot' => 'Inspect erosion points, lightning protection, and visible structural defects.',
                'status' => 'completed',
                'notes' => 'Minor erosion observed on blade A. Monitoring recommended for next cycle.',
                'performed_by_user_id' => $userIds['auditor'],
                'due_at' => '2026-03-24 11:30:00',
                'completed_at' => '2026-03-24 11:05:00',
            ], $now),
            $this->upsertInterventionTask($interventionId, $taskIds['torque'], [
                'sequence_no' => 3,
                'task_label' => 'Verify tower bolt torque',
                'task_description_snapshot' => 'Confirm torque values against the preventive maintenance baseline.',
                'status' => 'completed',
                'notes' => 'All sampled bolts within tolerance.',
                'performed_by_user_id' => $userIds['manager'],
                'due_at' => '2026-03-24 12:30:00',
                'completed_at' => '2026-03-24 12:20:00',
            ], $now),
        ];

        $this->upsertEvent($interventionId, [
            'event_type' => 'planned',
            'event_message' => 'Preventive maintenance intervention scheduled in the planning board.',
            'event_data' => ['source' => 'scheduler', 'priority' => 'medium'],
            'happened_at' => '2026-03-22 08:05:00',
            'created_by_user_id' => $userIds['owner'],
        ], $now);

        $this->upsertEvent($interventionId, [
            'event_type' => 'started',
            'event_message' => 'Field team started work on turbine QTM-TUR-001.',
            'event_data' => ['crew' => 'team-alpha'],
            'happened_at' => '2026-03-24 09:15:00',
            'created_by_user_id' => $userIds['manager'],
        ], $now);

        $this->upsertEvent($interventionId, [
            'event_type' => 'completed',
            'event_message' => 'Intervention closed after all planned tasks were completed.',
            'event_data' => ['task_count' => 3, 'requires_follow_up' => true],
            'happened_at' => '2026-03-24 12:45:00',
            'created_by_user_id' => $userIds['auditor'],
        ], $now);

        $this->upsertFile($interventionId, $interventionTaskIds[1], [
            'uploaded_by_user_id' => $userIds['auditor'],
            'file_category' => 'photo',
            'original_name' => 'blade-leading-edge-inspection.jpg',
            'stored_name' => 'mi-2026-0001-blade-leading-edge.jpg',
            'storage_path' => 'uploads/maintenance/mi-2026-0001/blade-leading-edge.jpg',
            'mime_type' => 'image/jpeg',
            'file_size_bytes' => 2483200,
            'checksum_sha256' => hash('sha256', 'mi-2026-0001-blade-leading-edge'),
            'description' => 'Photo evidence of leading-edge erosion observed during the intervention.',
        ], $now);

        $this->upsertBlockchainTransaction($interventionId, [
            'network' => 'polygon-pos',
            'transaction_hash' => '0x8bcb8e0d45b83c4d87fd67b14d8b7dbeff8f67512f7f28e5217f839651c9e201',
            'contract_address' => '0x6c4386346a0fe9c30647d2e91d3cc3c10aa7a447',
            'block_number' => 56124012,
            'status' => 'confirmed',
            'anchor_type' => 'intervention',
            'anchored_hash' => hash('sha256', 'MI-2026-0001|completed|2026-03-24 12:45:00'),
        ], $now);
    }

    private function upsertOrganization(string $now): int
    {
        $data = [
            'name' => 'Quantum Wind Operations Demo',
            'slug' => 'quantum-demo-wind',
            'organization_type' => 'operator',
            'country_code' => 'PT',
            'email' => 'ops-demo@quantum.local',
            'website' => 'https://demo.quantum.local',
            'status' => 'active',
        ];

        $existing = $this->db->table('organizations')->where('slug', $data['slug'])->get()->getRowArray();

        if ($existing) {
            $this->db->table('organizations')->where('id', $existing['id'])->update($data + ['updated_at' => $now]);

            return (int) $existing['id'];
        }

        $this->db->table('organizations')->insert($data + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);

        return (int) $this->db->insertID();
    }

    private function seedDemoUsers(int $organizationId, string $now): array
    {
        $users = [
            'owner' => [
                'name' => 'Quantum Demo Owner',
                'email' => 'demo@quantum.local',
                'password' => 'Demo123!',
                'role' => 'user',
                'membership_role' => 'owner',
            ],
            'manager' => [
                'name' => 'Ines Field Manager',
                'email' => 'ines.manager@quantum.local',
                'password' => 'Demo123!',
                'role' => 'user',
                'membership_role' => 'manager',
            ],
            'auditor' => [
                'name' => 'Rui Compliance Auditor',
                'email' => 'rui.auditor@quantum.local',
                'password' => 'Demo123!',
                'role' => 'user',
                'membership_role' => 'auditor',
            ],
        ];

        $ids = [];

        foreach ($users as $key => $user) {
            $existing = $this->db->table('users')->where('email', $user['email'])->get()->getRowArray();

            $payload = [
                'name' => $user['name'],
                'email' => $user['email'],
                'password_hash' => password_hash($user['password'], PASSWORD_DEFAULT),
                'role' => $user['role'],
                'status' => 'active',
            ];

            if ($existing) {
                $userId = (int) $existing['id'];
                $this->db->table('users')->where('id', $userId)->update($payload + ['updated_at' => $now]);
            } else {
                $this->db->table('users')->insert($payload + [
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
                $userId = (int) $this->db->insertID();
            }

            $membership = $this->db->table('organization_memberships')
                ->where('organization_id', $organizationId)
                ->where('user_id', $userId)
                ->get()
                ->getRowArray();

            $membershipPayload = [
                'organization_id' => $organizationId,
                'user_id' => $userId,
                'role' => $user['membership_role'],
                'status' => 'active',
                'joined_at' => '2026-03-20 09:00:00',
            ];

            if ($membership) {
                $this->db->table('organization_memberships')
                    ->where('id', $membership['id'])
                    ->update($membershipPayload + ['updated_at' => $now]);
            } else {
                $this->db->table('organization_memberships')->insert($membershipPayload + [
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
            }

            $ids[$key] = $userId;
        }

        return $ids;
    }

    private function upsertSite(int $organizationId, string $now): int
    {
        $data = [
            'organization_id' => $organizationId,
            'name' => 'Mafra Ridge Wind Farm',
            'site_code' => 'QTM-WF-PT-001',
            'site_type' => 'wind_farm',
            'country_code' => 'PT',
            'region' => 'Lisbon',
            'location' => 'Mafra, Portugal',
            'latitude' => 38.9406000,
            'longitude' => -9.3274000,
            'commissioned_at' => '2024-04-18',
            'status' => 'active',
        ];

        $existing = $this->db->table('sites')
            ->where('organization_id', $organizationId)
            ->where('site_code', $data['site_code'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('sites')->where('id', $existing['id'])->update($data + ['updated_at' => $now]);

            return (int) $existing['id'];
        }

        $this->db->table('sites')->insert($data + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);

        return (int) $this->db->insertID();
    }

    private function upsertTurbine(int $siteId, array $data, string $now): int
    {
        $payload = $data + ['site_id' => $siteId];
        $existing = $this->db->table('turbines')
            ->where('site_id', $siteId)
            ->where('turbine_code', $data['turbine_code'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('turbines')->where('id', $existing['id'])->update($payload + ['updated_at' => $now]);

            return (int) $existing['id'];
        }

        $this->db->table('turbines')->insert($payload + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);

        return (int) $this->db->insertID();
    }

    private function upsertTask(int $organizationId, array $data, string $now): int
    {
        $payload = $data + ['organization_id' => $organizationId];
        $existing = $this->db->table('maintenance_tasks')
            ->where('organization_id', $organizationId)
            ->where('task_code', $data['task_code'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('maintenance_tasks')->where('id', $existing['id'])->update($payload + ['updated_at' => $now]);

            return (int) $existing['id'];
        }

        $this->db->table('maintenance_tasks')->insert($payload + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);

        return (int) $this->db->insertID();
    }

    private function upsertIntervention(int $organizationId, int $siteId, int $turbineId, array $data, string $now): int
    {
        $payload = $data + [
            'organization_id' => $organizationId,
            'site_id' => $siteId,
            'turbine_id' => $turbineId,
        ];

        $existing = $this->db->table('maintenance_interventions')
            ->where('organization_id', $organizationId)
            ->where('intervention_code', $data['intervention_code'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('maintenance_interventions')->where('id', $existing['id'])->update($payload + ['updated_at' => $now]);

            return (int) $existing['id'];
        }

        $this->db->table('maintenance_interventions')->insert($payload + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);

        return (int) $this->db->insertID();
    }

    private function upsertInterventionTask(int $interventionId, int $taskId, array $data, string $now): int
    {
        $payload = $data + [
            'maintenance_intervention_id' => $interventionId,
            'maintenance_task_id' => $taskId,
        ];

        $existing = $this->db->table('maintenance_intervention_tasks')
            ->where('maintenance_intervention_id', $interventionId)
            ->where('sequence_no', $data['sequence_no'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('maintenance_intervention_tasks')->where('id', $existing['id'])->update($payload + ['updated_at' => $now]);

            return (int) $existing['id'];
        }

        $this->db->table('maintenance_intervention_tasks')->insert($payload + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);

        return (int) $this->db->insertID();
    }

    private function upsertEvent(int $interventionId, array $data, string $now): void
    {
        $payload = [
            'maintenance_intervention_id' => $interventionId,
            'event_type' => $data['event_type'],
            'event_message' => $data['event_message'],
            'event_data' => json_encode($data['event_data'], JSON_UNESCAPED_SLASHES),
            'happened_at' => $data['happened_at'],
            'created_by_user_id' => $data['created_by_user_id'] ?? null,
        ];

        $existing = $this->db->table('maintenance_events')
            ->where('maintenance_intervention_id', $interventionId)
            ->where('event_type', $data['event_type'])
            ->where('happened_at', $data['happened_at'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('maintenance_events')->where('id', $existing['id'])->update($payload + ['updated_at' => $now]);

            return;
        }

        $this->db->table('maintenance_events')->insert($payload + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);
    }

    private function upsertFile(int $interventionId, ?int $interventionTaskId, array $data, string $now): void
    {
        $payload = $data + [
            'maintenance_intervention_id' => $interventionId,
            'maintenance_intervention_task_id' => $interventionTaskId,
        ];

        $existing = $this->db->table('maintenance_files')
            ->where('maintenance_intervention_id', $interventionId)
            ->where('stored_name', $data['stored_name'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('maintenance_files')->where('id', $existing['id'])->update($payload + ['updated_at' => $now]);

            return;
        }

        $this->db->table('maintenance_files')->insert($payload + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);
    }

    private function upsertBlockchainTransaction(int $interventionId, array $data, string $now): void
    {
        $payload = $data + ['maintenance_intervention_id' => $interventionId];
        $existing = $this->db->table('blockchain_transactions')
            ->where('transaction_hash', $data['transaction_hash'])
            ->get()
            ->getRowArray();

        if ($existing) {
            $this->db->table('blockchain_transactions')->where('id', $existing['id'])->update($payload + ['updated_at' => $now]);

            return;
        }

        $this->db->table('blockchain_transactions')->insert($payload + [
            'created_at' => $now,
            'updated_at' => $now,
        ]);
    }
}
