package auctiora;

import lombok.extern.slf4j.Slf4j;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

@Slf4j
public class ScraperDataAdapter {
   
   private static final DateTimeFormatter[] TIMESTAMP_FORMATS = {
           DateTimeFormatter.ISO_LOCAL_DATE_TIME,
           DateTimeFormatter.ISO_DATE_TIME,
           DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
   };
   
   static AuctionInfo fromScraperAuction(ResultSet rs) throws SQLException {
      // Parse "A7-39813" → auctionId=39813, type="A7"
      var auctionIdStr = rs.getString("auction_id");
      var auctionId    = extractNumericId(auctionIdStr);
      var type         = extractTypePrefix(auctionIdStr);
      
      // Split "Cluj-Napoca, RO" → city="Cluj-Napoca", country="RO"
      var location      = rs.getString("location");
      var locationParts = parseLocation(location);
      var city          = locationParts[0];
      var country       = locationParts[1];
      
      // Map field names
      var lotCount    = getIntOrDefault(rs, "lots_count", 0);
      var closingTime = parseTimestamp(getStringOrNull(rs, "first_lot_closing_time"));
      
      return new AuctionInfo(
              auctionId,
              rs.getString("title"),
              location,
              city,
              country,
              rs.getString("url"),
              type,
              lotCount,
              closingTime
      );
   }
   
   public static Lot fromScraperLot(ResultSet rs) throws SQLException {
      var lotId  = extractNumericId(rs.getString("lot_id"));
      var saleId = extractNumericId(rs.getString("auction_id"));
      
      var bidStr   = getStringOrNull(rs, "current_bid");
      var bid      = parseBidAmount(bidStr);
      var currency = parseBidCurrency(bidStr);
      
      var closing = parseTimestamp(getStringOrNull(rs, "closing_time"));
      
      return new Lot(
              saleId,
              lotId,
              rs.getString("title"),
              getStringOrDefault(rs, "description", ""),
              "", "", 0,
              getStringOrDefault(rs, "category", ""),
              bid,
              currency,
              rs.getString("url"),
              closing,
              false
      );
   }
   
   public static int extractNumericId(String id) {
      if (id == null || id.isBlank()) return 0;
      // Remove the type prefix (e.g., "A7-") first, then extract all digits
      // "A7-39813" → "39813" → 39813
      // "A1-28505-5" → "28505-5" → "285055"
      var afterPrefix = id.indexOf('-') >= 0 ? id.substring(id.indexOf('-') + 1) : id;
      var digits = afterPrefix.replaceAll("\\D+", "");
      return digits.isEmpty() ? 0 : Integer.parseInt(digits);
   }
   
   private static String extractTypePrefix(String id) {
      if (id == null) return "";
      var idx = id.indexOf('-');
      return idx > 0 ? id.substring(0, idx) : "";
   }
   
   private static String[] parseLocation(String location) {
      if (location == null || location.isBlank()) return new String[]{ "", "" };
      var parts   = location.split(",\\s*");
      var city    = parts[0].trim();
      var country = parts.length > 1 ? parts[parts.length - 1].trim() : "";
      return new String[]{ city, country };
   }
   
   private static double parseBidAmount(String bid) {
      if (bid == null || bid.isBlank() || bid.toLowerCase().contains("no")) return 0.0;
      var cleaned = bid.replaceAll("[^0-9.]", "");
      try {
         return cleaned.isEmpty() ? 0.0 : Double.parseDouble(cleaned);
      } catch (NumberFormatException e) {
         return 0.0;
      }
   }
   
   private static String parseBidCurrency(String bid) {
      if (bid == null) return "EUR";
      return bid.contains("€") ? "EUR"
                               : bid.contains("$") ? "USD"
                                                   : bid.contains("£") ? "GBP"
                                                                       : "EUR";
   }
   
   private static LocalDateTime parseTimestamp(String ts) {
      if (ts == null || ts.isBlank()) return null;
      for (var fmt : TIMESTAMP_FORMATS) {
         try {
            return LocalDateTime.parse(ts, fmt);
         } catch (DateTimeParseException ignored) { }
      }
      log.info("Unable to parse timestamp: {}", ts);
      return null;
   }
   
   private static String getStringOrNull(ResultSet rs, String col) throws SQLException {
      return rs.getString(col);
   }
   
   private static String getStringOrDefault(ResultSet rs, String col, String def) throws SQLException {
      var v = rs.getString(col);
      return v != null ? v : def;
   }
   
   private static int getIntOrDefault(ResultSet rs, String col, int def) throws SQLException {
      var v = rs.getInt(col);
      return rs.wasNull() ? def : v;
   }
}
