# -*- coding: utf-8 -*-
from qgis.core import (
    QgsProcessingAlgorithm,
    QgsProcessingParameterFeatureSource,
    QgsProcessingParameterField,
    QgsProcessingParameterString,
    QgsProcessingParameterFolderDestination,
    QgsProcessingParameterBoolean,
    QgsProcessingParameterEnum,
    QgsProcessingException
)
import urllib.request
import urllib.parse
import ssl
import os
import time
from .license_guard import SupabaseGuard

class DownloadRBIToolPro(QgsProcessingAlgorithm):
    # Constants
    ADMIN_LAYER = 'ADMIN_LAYER'
    FIELD_KAB = 'FIELD_KAB'
    FIELD_PROV = 'FIELD_PROV'
    KABUPATEN = 'KABUPATEN'
    TOKEN = 'TOKEN'
    SKALA = 'SKALA'
    OUTPUT_FOLDER = 'OUTPUT_FOLDER'

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFeatureSource(
            self.ADMIN_LAYER, 'Layer Administrasi', [2] # Polygon
        ))
        
        self.addParameter(QgsProcessingParameterField(
            self.FIELD_KAB, 'Field Kabupaten', parentLayerParameterName=self.ADMIN_LAYER, type=QgsProcessingParameterField.String
        ))
        
        self.addParameter(QgsProcessingParameterField(
            self.FIELD_PROV, 'Field Provinsi', parentLayerParameterName=self.ADMIN_LAYER, type=QgsProcessingParameterField.String
        ))
        
        self.addParameter(QgsProcessingParameterString(
            self.KABUPATEN, 'Nama Kabupaten/Kota (Manual Input)', optional=True
        ))
        
        self.addParameter(QgsProcessingParameterString(
            self.TOKEN, 'API Token'
        ))
        
        self.addParameter(QgsProcessingParameterEnum(
            self.SKALA, 
            'Skala Peta', 
            options=['25K', '50K'], 
            defaultValue=0, 
            allowMultiple=False
        ))
        
        self.addParameter(QgsProcessingParameterFolderDestination(
            self.OUTPUT_FOLDER, 'Output Folder'
        ))

    def processAlgorithm(self, parameters, context, feedback):
        # 1. License Check
        feedback.pushInfo("[1/4] Memeriksa lisensi...")
        is_valid, msg, info = SupabaseGuard.check_license("BIG Downloader QGIS", "free")
        feedback.pushInfo(msg)
        if not is_valid:
            raise QgsProcessingException("Gagal memvalidasi lisensi.")

        # 2. Get Params
        layer = self.parameterAsSource(parameters, self.ADMIN_LAYER, context)
        field_kab = self.parameterAsString(parameters, self.FIELD_KAB, context)
        field_prov = self.parameterAsString(parameters, self.FIELD_PROV, context)
        kab_input = self.parameterAsString(parameters, self.KABUPATEN, context)
        token = self.parameterAsString(parameters, self.TOKEN, context)
        
        skala_idx = self.parameterAsEnum(parameters, self.SKALA, context)
        skala_opts = ['25K', '50K']
        skala = skala_opts[skala_idx]
        
        output_folder = self.parameterAsString(parameters, self.OUTPUT_FOLDER, context)
        
        # Handle Temporary Output
        if output_folder == 'TEMPORARY_OUTPUT':
             output_folder = os.path.join(tempfile.gettempdir(), 'BIG_RBI_Output')
             if not os.path.exists(output_folder):
                 os.makedirs(output_folder)
             feedback.pushInfo(f"Info: Menggunakan folder sementara: {output_folder}")

        # 3. Determine Kabupaten & Province
        final_kab = ""
        final_prov = ""

        # Logic: QgsProcessingFeatureSource features are ALREADY filtered if selectedFeaturesOnly=True
        # So we just need to count them or iterate them.
        feature_count = layer.featureCount()
        
        if feature_count > 0:
             # Use the first feature found
             iterator = layer.getFeatures()
             feat = next(iterator, None)
             
             if feat:
                 final_kab = str(feat[field_kab])
                 final_prov = str(feat[field_prov])
                 feedback.pushInfo(f"Info: Menggunakan fitur terpilih ({feature_count}): {final_kab}, {final_prov}")
                 
             if feature_count > 1:
                 feedback.pushInfo(f"Warning: {feature_count} fitur terpilih. Menggunakan yang pertama.")
                 
        else:
             # If no features in source, check manual input
             if kab_input:
                 feedback.pushInfo(f"[2/4] Mencari lokasi {kab_input}...")
                 for feat in layer.getFeatures(): # This might not yield if the source was restricted??
                     # Wait, if layer is restricted to selected-only and selection is empty, this loop does nothing.
                     # But parameterAsSource respects the flag. If selection is empty, source is empty.
                     # If user intends to use manual input, they should probably NOT check "Selected features only".
                     # However, if they checked it but selected nothing, they get emptiness.
                     pass 
                     
                 # To support manual input when "Selected features only" IS CHECKED but empty:
                 # We can't search the layer easily because the source is restricted.
                 # We have to advise user to UNCHECK "Selected features only" if they want to search the whole layer.
                 # OR rely on manual input processing?
                 pass

             # Re-eval strategy:
             # If "Selected features only" is checked (which creates a subset source), and it's empty:
             # We can't search for "kab_input" in the full layer because we don't handle the full layer.
             # So we must Error or rely solely on manual input if we don't need to validate?
             # But validasi prov needed.
             
             # If manual input provided and source is empty (due to selection flag), we can't validate against layer.
             # So raise error advising user.
             if kab_input:
                  raise QgsProcessingException("Fitur tidak ditemukan dalam seleksi. Hilangkan centang 'Selected features only' jika ingin mencari di seluruh layer.")
             else:
                  raise QgsProcessingException("Harap pilih fitur di peta ATAU isi Nama Kabupaten secara manual (dan uncheck 'Selected features only').")

        # Fallback validation
        if not final_kab or not final_prov:
             if kab_input and not layer: # Special case if layer param optional? (It's not)
                 pass
             elif feature_count > 0: # Should have been set above
                 pass
             else:
                 # Case: User didn't check 'selected' (so full layer), but didn't provide manual input?
                 # feature_count would be TOTAL (e.g. 500).
                 # We shouldn't just pick the first one (Aceh).
                 # So if feature_count > 10 (arbitrary) and kab_input is empty -> Error.
                 if feature_count > 1 and not kab_input:
                     raise QgsProcessingException(f"Terdapat {feature_count} fitur. Harap 'Select' satu fitur spesifik atau isi manual.")
                 
                 # If full layer and kab_input provided, we search manually:
                 if kab_input:
                      feedback.pushInfo(f"[2/4] Mencari lokasi {kab_input}...")
                      # Since feature_count > 0, we can iterate.
                      found = False
                      for feat in layer.getFeatures():
                           k = str(feat[field_kab])
                           p = str(feat[field_prov])
                           if k.strip().lower() == kab_input.strip().lower():
                               final_kab = k
                               final_prov = p
                               found = True
                               break
                      if not found:
                           raise QgsProcessingException(f"Kabupaten {kab_input} tidak ditemukan di layer.")

        feedback.pushInfo(f"Info: Target Download: {final_kab}, {final_prov}")

        # 4. Download
        ctx = ssl.create_default_context()
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE

        url = (
            "https://tanahair.indonesia.go.id/api-inageo/unduh/rbi?"
            f"token={token}&"
            f"prov={urllib.parse.quote(prov_found)}&"
            f"kab={urllib.parse.quote(kab_input)}&"
            f"skala={skala}"
        )
        feedback.pushInfo(f"Info: URL Request siap.")
        feedback.pushInfo(f"\n=== MENGUNDUH DATA ===")
        # feedback.pushInfo(f"Sedang mengunduh file dari server...")

        timestamp = time.strftime("%Y%m%d_%H%M%S")
        safe_kab = kab_input.replace(' ', '_')
        filename = f"RBI_{safe_kab}_{skala}_{timestamp}.zip"
        
        # Ensure output folder exists
        if not os.path.exists(output_folder):
            try: os.makedirs(output_folder, exist_ok=True)
            except: pass
            
        output_path = os.path.join(output_folder, filename)

        try:
            req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
            request_start = time.time()
            # URL is always HTTPS (tanahair.indonesia.go.id) - nosec B310
            with urllib.request.urlopen(req, context=ctx, timeout=300) as response:  # nosec B310
                total_size = int(response.info().get('Content-Length') or 0)
                downloaded = 0
                chunk_size = 8192
                
                with open(output_path, 'wb') as f:
                    while True:
                        if feedback.isCanceled():
                            break
                        chunk = response.read(chunk_size)
                        if not chunk:
                            break
                        f.write(chunk)
                        downloaded += len(chunk)
                        if total_size > 0:
                            feedback.setProgress(int((downloaded/total_size)*100))
            
            feedback.pushInfo(f"Selesai! Output tersimpan di: {output_path}")

        except Exception as e:
            raise QgsProcessingException(f"Gagal mengunduh: {str(e)}")

        return {self.OUTPUT_FOLDER: output_path}

    def name(self):
        return 'download_rbi_tool_pro'

    def displayName(self):
        return '3. Download RBI'

    def group(self):
        return 'BIG Downloader Tools'

    def groupId(self):
        return 'big_downloader_v2'

    def icon(self):
        import os
        from qgis.PyQt.QtGui import QIcon
        return QIcon(os.path.join(os.path.dirname(__file__), '..', 'images', 'icon_rbi.png'))

    def createInstance(self):
        return DownloadRBIToolPro()
