use ../../../../core/nulib/lib_provisioning/config/accessor.nu *

export def upcloud_sel_data_table [
  data: any
  id: string
] { 
  ($data | where {|it| $it.id == $id } | get -o table | get -o 0) 
}

export def upcloud_get_plan_prefix [
  id: string 
] { 
  match $id {
    "general-purpose" | "general" => "",
    "developer-plans" | "dev" => "DEV-",
    "high-cpu-plans" | "high-cpu" | "cpu" => "HICPU-",
    "high-memory-plans" | "high-memory" | "memory" | "ram" => "HIMEM-",
    _ => "",
  }
}
export def upcloud_get_id_from_plan [
  plan: string
] {
  if ($plan | str starts-with "HICPU-") {
    "high-cpu-plans"
  } else if ($plan | str starts-with "HIMEM-") {
    "high-memory-plans"
  } else if ($plan | str starts-with "DEV-") {
    "developer-plans"
  } else {
    "general-purpose"
  }
}
export def upcloud_sel_table_item [
  data: list
  key: string
  condition: string
  value: string
] { 
  ($data | where {|it|
    let item_data = match $key {
      "memory" | "ram" =>  ($it  | get $key | get 0 | str replace "GB" "" | str trim),
      _ => ($it  | get $key | get 0 ),
    }
    (match $condition {
      "lt" | "<" => (($item_data | into int ) < ($value | str replace "GB" "" | into int)),
      "lte" | "<=" => (($item_data | into int ) <= ($value | str replace "GB" "" | into int)),
      _ => false
    })
  }| flatten)
}
export def upcloud_get_price [
  all_data: record
  key: string
  price_col: string = "global_price"
] { 
  let data = ($all_data | get -o item)
  let str_price_col = if ($price_col | is-empty) { "global_price" } else { $price_col }
  match ($all_data | get -o target) {
    "server" => { 
      let table_key = if $key == "unit" { "hour" } else { $key }
      let value = ($data | get -o $str_price_col | flatten | get -o $table_key | default "" | str replace -a "€" "" ) 
      if $key == "unit" { 
        $"($value | get -o 0) Hrs" 
      } else if ($value | is-not-empty) { 
        ($value | get -o 0 | into float) 
      } else { 
        0
      }
    },
    "storage" => { 
      # Index 0 should be part of the server PLAN
      let it =  ($all_data | get -o src )
      if ($it | is-empty) or  ($it | get -o item | is-empty) { return 0 }
      if ($it.index) == 0 { return 0 }
      let storage = $it.item
      let storage_type = match ($storage | get -o voltype) {
        "maxiops" => "MaxIOPS",
        "hdd" => "HDD",
        "custom" => "Custom image",
      }
      let month = ($data | find $storage_type | select $str_price_col | flatten | into record | get -o month | default "" | str replace -a "€" "" | into float) 
      let hour = ($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float) 
      match $key { 
        "unit" => 
            $"($data | find $storage_type | select $str_price_col | flatten | into record | get -o month | default "" | str replace -a "€" "") GB-Mo",
        "month" => 
            ($data | find $storage_type | select $str_price_col | flatten | into record | get -o month | default "" | str replace -a "€" "" | into float),
        "day" => 
          (($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float) * 24),
        "hour" => 
          ($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float),
        _ => 0,
      }
    },
    "networking" => { 
      0
    },
    "backups" => { 
      0
    },
    _ => { 
      0
    }
  }
}
export def upcloud_get_item_for_storage [
  server: record
  settings: record
  cloud_data: record
] { 
  let data = ($cloud_data | get -o $server.provider| get -o "block_storage")
  if ($data | is-empty) { return {} }
  ($data | get -o table | get -o 0) 
}
export def upcloud_get_item_for_server [
  server: record
  settings: record
  cloud_data: record
] { 
  let data = ($cloud_data | get -o $server.provider | get -o "servers")
  if ($data | is-empty) { return {} }
  let plan = ($server | get -o plan | default "")
  let key_id = (upcloud_get_id_from_plan $plan)
  let cloud_table_data = (upcloud_sel_data_table $data $key_id)
  if ($cloud_table_data | is-empty) { return {} }
  ($cloud_table_data | where {|it| 
    ($it | get -o plan ) == $plan 
  } | get -o 0)
}
export def upcloud_clean_table [
  id: string
  data: string
  target: string
] { 
  let table = ( $data | split row "<tr>" | where {|it| $it | str starts-with "<" } |
     each {|it| $it | str replace -a -r "<(\/td|sup|\/sup|small|\/small|b|\/b|br|\/tr|tbody|\/tbody|\/thead|\/th)>" "" }
  ) 
  let table_cols = if ($table | get 0 | str contains "<th>") { 
    ($table | get 0 | split row "<th>")
  } else { 
    ($table | get 0 | split row "<td>")
  }
  let cols = ($table_cols | where {|it| $it != "" } | str replace " *" " "  |
    str trim | str downcase |  str replace " " "_" | str replace 'price*' 'price')
  let plan_prefix = (upcloud_get_plan_prefix $id)
  let res = ( $table | drop nth 0 | each {|line| $line | split column "<td>" -c ...$cols } | 
  each {|it| 
      #if  $target == "networking" => { print $it }
      match $target {
        "block-storage" => { 
          $it |  
            update storage_type $"($it | get -o 'storage_type' | get -o 0 )" |  
            update global_price ($it| get -o global_price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) | 
            update helsinki_price ($it| get -o helsinki_price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) 
        },
        "object-storage" => {
          $it |  
            update price ($it| get -o price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
        },
        "cloud-servers" | "servers" => {
          let helsinki_price = ($it| get -o helsinki_price | get -o 0 | default "") 
          if ($helsinki_price | is-not-empty) {
            $it | insert plan $"($plan_prefix)($it | get -o 'cpu_cores' | get -o 0 )xCPU-($it | get -o 'memory' | get -o 0 | str replace ' ' '')" |  
              update global_price ($it| get -o global_price | get -o 0 | default "" | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
              update helsinki_price ($it| get -o helsinki_price | get -o 0 | default "" | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) 
          } else { 
            $it | insert plan $"($plan_prefix)($it | get -o 'cpu_cores' | get -o 0 )xCPU-($it | get -o 'memory' | get -o 0 | str replace ' ' '')" |  
              update global_price ($it| get -o global_price | get -o 0 | default "" | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
          }
        },
        "simple-backups" => {
          $it | update global_price ($it| get -o global_price | get -o 0  | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
                update helsinki_price ($it| get -o helsinki_price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) 
        },
        "networking" => {
          $it | update price ($it| get -o price | get -o 0  | str replace "Price" "---"  | str replace "  " " " |   
            parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h|(?<price>.*)" | get -o 0) 
        },
        _ => { $it },
      }
  })
  ($res | flatten)
}
export def upcloud_get_provider_path [
  settings: record
  server: record
] {
  let data_path = if ($settings.data.prov_data_dirpath | str starts-with "." ) {
      ($settings.src_path | path join $settings.data.prov_data_dirpath)
  } else { $settings.data.prov_data_dirpath } 
  if not ($data_path | path exists) { mkdir $data_path }
  ($data_path | path join $"($server.provider)_prices.((get-provisioning-wk-format))")
}
export def upcloud_load_infra_storages_info [
  settings: record
  server: record
  error_exit: bool
] { 
  let data = (upcloud_load_infra_servers_info $settings $server $error_exit)
  let res =  ($data | get -o "block-storage")
  print ($res | table -e)
  $res
}
export def upcloud_load_infra_servers_info [
  settings: record
  server: record
  error_exit: bool
]: nothing -> record  { 
  let provider_prices_path = (upcloud_get_provider_path $settings $server)
  let data = if ($provider_prices_path | path exists) { 
      open $provider_prices_path
  } else { 
    let url = "https://upcloud.com/pricing" 
    let pricing_html_path = ((get-providers-path) | path join "upcloud" | path join "pricing.html")
    { servers: (upcloud_load_infra $url $pricing_html_path "cloud-servers"),
      block_storage: (upcloud_load_infra $url $pricing_html_path "block-storage"),
      object_storage: (upcloud_load_infra $url $pricing_html_path "object-storage"),
      backups: (upcloud_load_infra $url $pricing_html_path "simple-backups"),
      networking: (upcloud_load_infra $url $pricing_html_path "networking"),
    }
  }
  if ($provider_prices_path | path exists) { return $data }
  if (get-provisioning-wk-format) == "json" { 
    $data | to json | save -f $provider_prices_path
  } else { 
    $data | to yaml | save -f $provider_prices_path
  }
  if (is-debug-enabled) {  print $"Price for ($server.provider) in: ($provider_prices_path | path basename)" }
  $data 
}
export def upcloud_load_infra [
  url: string
  html_path: string
  target: string = "servers"
]: nothing -> list { 
  let id_target = match $target { 
    "object" | "object-storage" | "os" => "object-storage",
    "block" | "block-storage" | "bs" => "block-storage",
    "server" | "servers" | "s" => "cloud-servers",
    "backup" | "simple-backups" | "s" => "simple-backups",
    "network" | "networking" | "s" => "networking",
    _ => "cloud-servers",
  }
  # cookie error if use curl o http get 
  let html_content  = if ($html_path | path exists) {
    open -r $html_path
  } else { 
    #let res = (http get $url -r )
    let res = (^curl -s $url | complete)
    if ($res.exit_code != 0) {
      print $"🛑 Error (_ansi red)($url)(_ansi reset):\n ($res.exit_code) ($res.stderr)"
      return ""
    } else { $res.stdout }
  }
  ($html_content | split row "<section "|  find $'id="($id_target)"'  | split row  role="tabpanel" | find "<table" | each {|it| 
      let id = ($it | parse --regex 'id="(?<id>.*?)"' | get id | get -o 0 | str replace -r "-tab$" "")
      let title = ($it | parse --regex '<h3>(?<title>.*?)<\/h3>' | get title | get -o 0) 
      let info = ($it | parse --regex '<\/h3><p>(?<info>.*?)<\/p>' | get info | get -o 0) 
      let table = ($it | parse --regex '<table\s*(?<table>.*?)<\/table>' | get table | get -o 0) 
      { id: $id, table: (upcloud_clean_table $id $table $id_target), title: $title, info: $info }
  })
  # mut $group_data = {}
  # for item in $data {
  #   print $item
  #   let group = ($item | get -o id)
  #   let table = ($item | get -o table) 
  #   print $group
  #   print ($table | flatten | table -e)
  #   if ($group | is-empty) { continue }
  #   # if ($group_data | get -o $group | is-empty) {
  #   #   $group_data = ($group_data | merge { $group: [($item | reject id)]})
  #   # } else { 
  #   #   $group_data = ($group_data | merge { $group: ($group_data  | get -o $group | append ($item | reject id))})
  #   # }
  # }
  # exit
  # $group_data
  # each { |it| $it | parse --regex 'id="(?<id>.*?)"(?<other>.*)<h3>(?<title>.*)<\/h3><p>(?<info>.*)</p>(?.*)<table\s*(?<table>.*)<\/table>' } 
  #   where {|it| $it | str starts-with "<" } |
  #print ($cloud_servers  | each {|it| select id table} | flatten | each {|it| 
  #let res = ($cloud_servers  | each {|it| select id table} | flatten | each {|it| 
  #    let id = ($it.id | str replace -r "-tab$" "")
  #    { id: $id, table: (upcloud_clean_table $id $it.table) } 
  #  }
  #)
}
export def upcloud_test_infra_servers [
] { 
  let data_infra_servers = (upcloud_load_infra_servers "https://upcloud.com/pricing") 
  let key_id = ($data_infra_servers | get id | input list "Select server group ")
  let cloud_data = (upcloud_sel_data_table $data_infra_servers $key_id)
  let mem_limit = (["4 GB" "8 GB" "16 GB" "32 GB" "64 GB" "96 GB" "128 GB" "256 GB" "512 GB" ] | input list "Select MEMORY limit ")

  let items = (upcloud_sel_table_item $cloud_data "memory" "lte" $mem_limit)
  print ($items | table -e)
  #let line = ($cloud_servers | get 0 | get table | get 1 ) 
  print $"From ($key_id) with ($mem_limit)\n"
  print $"memory  | cores | month | hour   | plan     "
  print "============================================="
  for line in $items {
    print ($"($line | get memory) \t| ($line | get cpu_cores) \t| (upcloud_get_price $line 'month')" + 
      $" \t| (upcloud_get_price $line 'hour') | ($line | get plan) "
    )
  }
}
