#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../include/chroma.h"

static char *trim_whitespace(char *str) {
  char *end;

  // Trim leading whitespace
  while (isspace((unsigned char)*str))
    str++;

  // All spaces?
  if (*str == 0)
    return str;

  // Trim trailing whitespace
  end = str + strlen(str) - 1;
  while (end > str && isspace((unsigned char)*end))
    end--;

  *(end + 1) = '\0';
  return str;
}

// Remove quotes from a string
static char *remove_quotes(char *str) {
  size_t len = strlen(str);
  if (len >= 2 && ((str[0] == '"' && str[len - 1] == '"') ||
                   (str[0] == '\'' && str[len - 1] == '\''))) {
    str[len - 1] = '\0';
    return str + 1;
  }
  return str;
}

// Parse boolean value from string
static bool parse_bool(const char *value) {
  if (!value)
    return false;

  if (strcasecmp(value, "true") == 0 || strcasecmp(value, "yes") == 0 ||
      strcasecmp(value, "1") == 0 || strcasecmp(value, "on") == 0) {
    return true;
  }

  return false;
}

// Parse scaling mode from string
static chroma_scale_mode_t parse_scale_mode(const char *value) {
  if (!value)
    return CHROMA_SCALE_FILL; // default

  if (strcasecmp(value, "fill") == 0) {
    return CHROMA_SCALE_FILL;
  } else if (strcasecmp(value, "fit") == 0) {
    return CHROMA_SCALE_FIT;
  } else if (strcasecmp(value, "stretch") == 0) {
    return CHROMA_SCALE_STRETCH;
  } else if (strcasecmp(value, "center") == 0) {
    return CHROMA_SCALE_CENTER;
  }

  chroma_log("WARN", "Unknown scaling mode: %s (using fill)", value);
  return CHROMA_SCALE_FILL;
}

// Parse filter quality from string
static chroma_filter_quality_t parse_filter_quality(const char *value) {
  if (!value)
    return CHROMA_FILTER_LINEAR; // default

  if (strcasecmp(value, "nearest") == 0) {
    return CHROMA_FILTER_NEAREST;
  } else if (strcasecmp(value, "linear") == 0) {
    return CHROMA_FILTER_LINEAR;
  } else if (strcasecmp(value, "bilinear") == 0) {
    return CHROMA_FILTER_BILINEAR;
  } else if (strcasecmp(value, "trilinear") == 0) {
    return CHROMA_FILTER_TRILINEAR;
  }

  chroma_log("WARN", "Unknown filter quality: %s (using linear)", value);
  return CHROMA_FILTER_LINEAR;
}

// Get string representation of scaling mode
static const char *scale_mode_to_string(chroma_scale_mode_t mode) {
  switch (mode) {
  case CHROMA_SCALE_FILL:
    return "fill";
  case CHROMA_SCALE_FIT:
    return "fit";
  case CHROMA_SCALE_STRETCH:
    return "stretch";
  case CHROMA_SCALE_CENTER:
    return "center";
  default:
    return "unknown";
  }
}

// Get string representation of filter quality
static const char *filter_quality_to_string(chroma_filter_quality_t quality) {
  switch (quality) {
  case CHROMA_FILTER_NEAREST:
    return "nearest";
  case CHROMA_FILTER_LINEAR:
    return "linear";
  case CHROMA_FILTER_BILINEAR:
    return "bilinear";
  case CHROMA_FILTER_TRILINEAR:
    return "trilinear";
  default:
    return "unknown";
  }
}

// Parse anchor position from string
static chroma_anchor_t parse_anchor(const char *value) {
  if (!value)
    return CHROMA_ANCHOR_CENTER;

  if (strcasecmp(value, "center") == 0) {
    return CHROMA_ANCHOR_CENTER;
  } else if (strcasecmp(value, "top") == 0) {
    return CHROMA_ANCHOR_TOP;
  } else if (strcasecmp(value, "bottom") == 0) {
    return CHROMA_ANCHOR_BOTTOM;
  } else if (strcasecmp(value, "left") == 0) {
    return CHROMA_ANCHOR_LEFT;
  } else if (strcasecmp(value, "right") == 0) {
    return CHROMA_ANCHOR_RIGHT;
  } else if (strcasecmp(value, "top-left") == 0 ||
             strcasecmp(value, "topleft") == 0) {
    return CHROMA_ANCHOR_TOP_LEFT;
  } else if (strcasecmp(value, "top-right") == 0 ||
             strcasecmp(value, "topright") == 0) {
    return CHROMA_ANCHOR_TOP_RIGHT;
  } else if (strcasecmp(value, "bottom-left") == 0 ||
             strcasecmp(value, "bottomleft") == 0) {
    return CHROMA_ANCHOR_BOTTOM_LEFT;
  } else if (strcasecmp(value, "bottom-right") == 0 ||
             strcasecmp(value, "bottomright") == 0) {
    return CHROMA_ANCHOR_BOTTOM_RIGHT;
  }

  chroma_log("WARN", "Unknown anchor: %s (using center)", value);
  return CHROMA_ANCHOR_CENTER;
}

// Get string representation of anchor position
static const char *anchor_to_string(chroma_anchor_t anchor) {
  switch (anchor) {
  case CHROMA_ANCHOR_CENTER:
    return "center";
  case CHROMA_ANCHOR_TOP:
    return "top";
  case CHROMA_ANCHOR_BOTTOM:
    return "bottom";
  case CHROMA_ANCHOR_LEFT:
    return "left";
  case CHROMA_ANCHOR_RIGHT:
    return "right";
  case CHROMA_ANCHOR_TOP_LEFT:
    return "top-left";
  case CHROMA_ANCHOR_TOP_RIGHT:
    return "top-right";
  case CHROMA_ANCHOR_BOTTOM_LEFT:
    return "bottom-left";
  case CHROMA_ANCHOR_BOTTOM_RIGHT:
    return "bottom-right";
  default:
    return "unknown";
  }
}

// Output-to-image mapping
static int add_output_mapping(chroma_config_t *config, const char *output_name,
                              const char *image_path,
                              chroma_scale_mode_t scale_mode,
                              chroma_filter_quality_t filter_quality,
                              chroma_anchor_t anchor, float anchor_x,
                              float anchor_y) {
  if (!config || !output_name || !image_path) {
    return CHROMA_ERROR_INIT;
  }

  if (config->mapping_count >= MAX_OUTPUTS) {
    chroma_log("ERROR", "Maximum number of output mappings reached (%d)",
               MAX_OUTPUTS);
    return CHROMA_ERROR_MEMORY;
  }

  // Validate string lengths to prevent buffer overflow
  size_t output_len = strlen(output_name);
  size_t path_len = strlen(image_path);

  if (output_len >= sizeof(config->mappings[0].output_name)) {
    chroma_log("ERROR", "Output name too long: %s (max %zu)", output_name,
               sizeof(config->mappings[0].output_name) - 1);
    return CHROMA_ERROR_CONFIG;
  }

  if (path_len >= sizeof(config->mappings[0].image_path)) {
    chroma_log("ERROR", "Image path too long: %s (max %zu)", image_path,
               sizeof(config->mappings[0].image_path) - 1);
    return CHROMA_ERROR_CONFIG;
  }

  chroma_config_mapping_t *mapping = &config->mappings[config->mapping_count];

  strcpy(mapping->output_name, output_name);
  strcpy(mapping->image_path, image_path);
  mapping->scale_mode = scale_mode;
  mapping->filter_quality = filter_quality;
  mapping->anchor = anchor;
  mapping->anchor_x = anchor_x;
  mapping->anchor_y = anchor_y;

  config->mapping_count++;

  chroma_log(
      "DEBUG",
      "Added mapping: %s -> %s (scale: %s, filter: %s, anchor: %s @ %.1f,%.1f)",
      output_name, image_path, scale_mode_to_string(scale_mode),
      filter_quality_to_string(filter_quality), anchor_to_string(anchor),
      anchor_x, anchor_y);
  chroma_log("TRACE", "Output mapping %d: '%s' -> '%s' (path length: %zu)",
             config->mapping_count, output_name, image_path, path_len);
  return CHROMA_OK;
}

// Initialize configuration with defaults
static void init_default_config(chroma_config_t *config) {
  if (!config)
    return;

  memset(config, 0, sizeof(chroma_config_t));

  config->daemon_mode = false;
  config->mapping_count = 0;

  // Set default scaling and filtering
  config->default_scale_mode = CHROMA_SCALE_FILL;
  config->default_filter_quality = CHROMA_FILTER_LINEAR;
  config->default_anchor = CHROMA_ANCHOR_CENTER;
  config->default_anchor_x = 50.0f; // center
  config->default_anchor_y = 50.0f; // center

  // Set default downsampling settings
  config->enable_downsampling = true; // enable by default, performance etc.
  config->max_output_width = 3840;    // 4K width
  config->max_output_height = 2160;   // 4K height
  config->min_scale_factor = 0.25f;   // don't scale below 25%

  // Set default image path (can be overridden)
  const char *home = getenv("HOME");
  if (home) {
    snprintf(config->default_image, sizeof(config->default_image),
             "%s/.config/chroma/default.jpg", home);
  } else {
    strcpy(config->default_image, "/usr/share/pixmaps/chroma-default.jpg");
  }
}

// Parse a single configuration line
static int parse_config_line(chroma_config_t *config, char *line,
                             int line_number) {
  if (!config || !line) {
    return CHROMA_ERROR_INIT;
  }

  // Skip empty lines and comments
  char *trimmed = trim_whitespace(line);
  if (*trimmed == '\0' || *trimmed == '#' || *trimmed == ';') {
    return CHROMA_OK;
  }

  // Find the equals sign
  char *equals = strchr(trimmed, '=');
  if (!equals) {
    chroma_log("WARN", "Invalid config line %d: no '=' found", line_number);
    return CHROMA_OK; // continue parsing
  }

  *equals = '\0';
  char *key = trim_whitespace(trimmed);
  char *value = trim_whitespace(equals + 1);

  value = remove_quotes(value);

  if (*key == '\0' || *value == '\0') {
    chroma_log("WARN", "Invalid config line %d: empty key or value",
               line_number);
    return CHROMA_OK;
  }

  // Parse configuration options
  if (strcasecmp(key, "default_image") == 0) {
    char *expanded_path = chroma_expand_path(value);
    const char *path_to_use = expanded_path ? expanded_path : value;
    size_t path_len = strlen(path_to_use);

    if (path_len >= sizeof(config->default_image)) {
      chroma_log("ERROR", "Default image path too long: %s (max %zu)",
                 path_to_use, sizeof(config->default_image) - 1);
      if (expanded_path) {
        free(expanded_path);
      }
      return CHROMA_ERROR_CONFIG;
    }

    strcpy(config->default_image, path_to_use);

    if (expanded_path) {
      chroma_log("DEBUG", "Set default image: %s -> %s", value, expanded_path);
      chroma_log("TRACE", "Default image path set: length=%zu, expanded='%s'",
                 path_len, expanded_path);
      free(expanded_path);
    } else {
      chroma_log("WARN", "Failed to expand path, using original: %s", value);
    }
  } else if (strcasecmp(key, "daemon") == 0 ||
             strcasecmp(key, "daemon_mode") == 0) {
    config->daemon_mode = parse_bool(value);
    chroma_log("DEBUG", "Set daemon mode: %s",
               config->daemon_mode ? "true" : "false");
    chroma_log("TRACE",
               "Daemon mode configuration: key='%s', value='%s', parsed=%s",
               key, value, config->daemon_mode ? "true" : "false");
  } else if (strcasecmp(key, "scale_mode") == 0 ||
             strcasecmp(key, "default_scale_mode") == 0) {
    config->default_scale_mode = parse_scale_mode(value);
    chroma_log("DEBUG", "Set default scale mode: %s",
               scale_mode_to_string(config->default_scale_mode));
    chroma_log("TRACE",
               "Scale mode configuration: key='%s', value='%s', parsed=%s", key,
               value, scale_mode_to_string(config->default_scale_mode));
  } else if (strcasecmp(key, "filter_quality") == 0 ||
             strcasecmp(key, "default_filter_quality") == 0) {
    config->default_filter_quality = parse_filter_quality(value);
    chroma_log("DEBUG", "Set default filter quality: %s",
               filter_quality_to_string(config->default_filter_quality));
    chroma_log("TRACE",
               "Filter quality configuration: key='%s', value='%s', parsed=%s",
               key, value,
               filter_quality_to_string(config->default_filter_quality));
  } else if (strcasecmp(key, "enable_downsampling") == 0) {
    config->enable_downsampling = parse_bool(value);
    chroma_log("DEBUG", "Set downsampling: %s",
               config->enable_downsampling ? "enabled" : "disabled");
  } else if (strcasecmp(key, "anchor") == 0) {
    config->default_anchor = parse_anchor(value);
    chroma_log("DEBUG", "Set default anchor: %s",
               anchor_to_string(config->default_anchor));
  } else if (strcasecmp(key, "anchor_x") == 0) {
    char *endptr = NULL;
    float ax = strtof(value, &endptr);
    if (endptr == value || *endptr != '\0') {
      chroma_log("WARN", "Invalid anchor_x: %s (not a number, using 50)",
                 value);
      config->default_anchor_x = 50.0f;
    } else if (ax < 0.0f || ax > 100.0f) {
      chroma_log("WARN", "Invalid anchor_x: %s (range 0-100, using 50)", value);
      config->default_anchor_x = 50.0f;
    } else {
      config->default_anchor_x = ax;
      chroma_log("DEBUG", "Set default anchor_x: %.1f", ax);
    }
  } else if (strcasecmp(key, "anchor_y") == 0) {
    char *endptr = NULL;
    float ay = strtof(value, &endptr);
    if (endptr == value || *endptr != '\0') {
      chroma_log("WARN", "Invalid anchor_y: %s (not a number, using 50)",
                 value);
      config->default_anchor_y = 50.0f;
    } else if (ay < 0.0f || ay > 100.0f) {
      chroma_log("WARN", "Invalid anchor_y: %s (range 0-100, using 50)", value);
      config->default_anchor_y = 50.0f;
    } else {
      config->default_anchor_y = ay;
      chroma_log("DEBUG", "Set default anchor_y: %.1f", ay);
    }
  } else if (strcasecmp(key, "max_output_width") == 0) {
    int width = atoi(value);
    if (width > 0 && width <= 16384) { // Reasonable limits
      config->max_output_width = width;
      chroma_log("DEBUG", "Set max output width: %d", width);
    } else {
      chroma_log("WARN", "Invalid max_output_width: %s (using 3840)", value);
    }
  } else if (strcasecmp(key, "max_output_height") == 0) {
    int height = atoi(value);
    if (height > 0 && height <= 16384) { // Reasonable limits
      config->max_output_height = height;
      chroma_log("DEBUG", "Set max output height: %d", height);
    } else {
      chroma_log("WARN", "Invalid max_output_height: %s (using 2160)", value);
    }
  } else if (strcasecmp(key, "min_scale_factor") == 0) {
    float factor = atof(value);
    if (factor > 0.0f && factor <= 1.0f) { // Valid range
      config->min_scale_factor = factor;
      chroma_log("DEBUG", "Set minimum scale factor: %.2f", factor);
    } else {
      chroma_log("WARN", "Invalid min_scale_factor: %s (using 0.25)", value);
    }
  } else if (strncasecmp(key, "output.", 7) == 0) {
    // Output-specific mapping: e.g., output.DP-1=/path/to/image.jpg
    const char *output_name = key + 7;
    if (*output_name == '\0') {
      chroma_log("WARN", "Invalid output mapping line %d: no output name",
                 line_number);
      return CHROMA_OK;
    }

    // Check for extended output configuration with properties
    // Format: output.DP-1.scale = fill
    // Format: output.DP-1.filter = linear
    char *dot = strchr(output_name, '.');
    if (dot) {
      // This is an output property (scale or filter)
      *dot = '\0';
      const char *property = dot + 1;

      // Find existing mapping for this output
      chroma_config_mapping_t *mapping = NULL;
      for (int i = 0; i < config->mapping_count; i++) {
        if (strcmp(config->mappings[i].output_name, output_name) == 0) {
          mapping = &config->mappings[i];
          break;
        }
      }

      if (!mapping) {
        chroma_log("WARN", "Output %s not found for property %s (line %d)",
                   output_name, property, line_number);
        return CHROMA_OK;
      }

      if (strcasecmp(property, "scale") == 0) {
        mapping->scale_mode = parse_scale_mode(value);
        chroma_log("DEBUG", "Set scale mode for output %s: %s", output_name,
                   scale_mode_to_string(mapping->scale_mode));
      } else if (strcasecmp(property, "filter") == 0) {
        mapping->filter_quality = parse_filter_quality(value);
        chroma_log("DEBUG", "Set filter quality for output %s: %s", output_name,
                   filter_quality_to_string(mapping->filter_quality));
      } else if (strcasecmp(property, "anchor") == 0) {
        mapping->anchor = parse_anchor(value);
        // Set anchor_x/anchor_y based on named anchor
        switch (mapping->anchor) {
        case CHROMA_ANCHOR_TOP:
          mapping->anchor_x = 50.0f;
          mapping->anchor_y = 0.0f;
          break;
        case CHROMA_ANCHOR_BOTTOM:
          mapping->anchor_x = 50.0f;
          mapping->anchor_y = 100.0f;
          break;
        case CHROMA_ANCHOR_LEFT:
          mapping->anchor_x = 0.0f;
          mapping->anchor_y = 50.0f;
          break;
        case CHROMA_ANCHOR_RIGHT:
          mapping->anchor_x = 100.0f;
          mapping->anchor_y = 50.0f;
          break;
        case CHROMA_ANCHOR_TOP_LEFT:
          mapping->anchor_x = 0.0f;
          mapping->anchor_y = 0.0f;
          break;
        case CHROMA_ANCHOR_TOP_RIGHT:
          mapping->anchor_x = 100.0f;
          mapping->anchor_y = 0.0f;
          break;
        case CHROMA_ANCHOR_BOTTOM_LEFT:
          mapping->anchor_x = 0.0f;
          mapping->anchor_y = 100.0f;
          break;
        case CHROMA_ANCHOR_BOTTOM_RIGHT:
          mapping->anchor_x = 100.0f;
          mapping->anchor_y = 100.0f;
          break;
        default:
          mapping->anchor_x = 50.0f;
          mapping->anchor_y = 50.0f;
          break;
        }
        chroma_log("DEBUG", "Set anchor for output %s: %s (x=%.1f, y=%.1f)",
                   output_name, anchor_to_string(mapping->anchor),
                   mapping->anchor_x, mapping->anchor_y);
      } else if (strcasecmp(property, "anchor_x") == 0) {
        float ax = atof(value);
        if (ax >= 0.0f && ax <= 100.0f) {
          mapping->anchor_x = ax;
          chroma_log("DEBUG", "Set anchor_x for output %s: %.1f", output_name,
                     ax);
        } else {
          mapping->anchor_x = 50.0f;
          chroma_log("WARN", "Invalid anchor_x: %s (range 0-100, using 50)",
                     value);
        }
      } else if (strcasecmp(property, "anchor_y") == 0) {
        float ay = atof(value);
        if (ay >= 0.0f && ay <= 100.0f) {
          mapping->anchor_y = ay;
          chroma_log("DEBUG", "Set anchor_y for output %s: %.1f", output_name,
                     ay);
        } else {
          mapping->anchor_y = 50.0f;
          chroma_log("WARN", "Invalid anchor_y: %s (range 0-100, using 50)",
                     value);
        }
      } else {
        chroma_log("WARN", "Unknown output property: %s (line %d)", property,
                   line_number);
      }

      return CHROMA_OK;
    }

    // Expand path before validation and storage
    char *expanded_path = chroma_expand_path(value);
    const char *path_to_validate = expanded_path ? expanded_path : value;

    // Validate image path
    if (chroma_image_validate(path_to_validate) != CHROMA_OK) {
      chroma_log("WARN", "Invalid image path for output %s: %s (expanded: %s)",
                 output_name, value, path_to_validate);
      if (expanded_path) {
        free(expanded_path);
      }
      return CHROMA_OK;
    }

    if (add_output_mapping(
            config, output_name, path_to_validate, config->default_scale_mode,
            config->default_filter_quality, config->default_anchor,
            config->default_anchor_x, config->default_anchor_y) != CHROMA_OK) {
      chroma_log("ERROR", "Failed to add output mapping: %s -> %s", output_name,
                 path_to_validate);
      if (expanded_path) {
        free(expanded_path);
      }
      return CHROMA_ERROR_CONFIG;
    }

    if (expanded_path) {
      free(expanded_path);
    }
  } else {
    chroma_log("WARN", "Unknown configuration key line %d: %s", line_number,
               key);
    chroma_log("TRACE", "Unrecognized config line %d: key='%s', value='%s'",
               line_number, key, value);
  }

  return CHROMA_OK;
}

// Load configuration from file
int chroma_config_load(chroma_config_t *config, const char *config_file) {
  if (!config) {
    return CHROMA_ERROR_INIT;
  }

  // Initialize with defaults
  init_default_config(config);

  if (!config_file) {
    chroma_log("INFO", "No config file specified, using defaults");
    return CHROMA_OK;
  }

  FILE *file = fopen(config_file, "r");
  if (!file) {
    if (errno == ENOENT) {
      chroma_log("INFO", "Config file not found: %s (using defaults)",
                 config_file);
      return CHROMA_OK;
    } else {
      chroma_log("ERROR", "Failed to open config file %s: %s", config_file,
                 strerror(errno));
      return CHROMA_ERROR_CONFIG;
    }
  }

  chroma_log("INFO", "Loading configuration from: %s", config_file);
  chroma_log("TRACE",
             "Starting configuration parsing, estimated config size: %ld bytes",
             chroma_get_file_size(config_file));

  char line[1024];
  int line_number = 0;
  int parse_errors = 0;

  while (fgets(line, sizeof(line), file)) {
    line_number++;

    char *newline = strchr(line, '\n');
    if (newline) {
      *newline = '\0';
    }

    if (parse_config_line(config, line, line_number) != CHROMA_OK) {
      parse_errors++;
    }
  }

  fclose(file);

  if (parse_errors > 0) {
    chroma_log("WARN", "Config file contained %d errors", parse_errors);
    // Continue anyway with partial configuration
  }

  chroma_log("INFO",
             "Loaded configuration: %d output mappings, default image: %s",
             config->mapping_count, config->default_image);

  // Log configuration memory usage
  size_t config_size =
      sizeof(chroma_config_t) +
      (config->mapping_count * sizeof(chroma_config_mapping_t));
  chroma_log_resource_allocation("config_data", config_size,
                                 "configuration structure");
  chroma_log_memory_stats("post-config-load");

  return CHROMA_OK;
}

// Free configuration resources
void chroma_config_free(chroma_config_t *config) {
  if (!config) {
    return;
  }

  // Log configuration deallocation
  size_t config_size =
      sizeof(chroma_config_t) +
      (config->mapping_count * sizeof(chroma_config_mapping_t));
  chroma_log_resource_deallocation("config_data", config_size,
                                   "configuration structure");

  chroma_log("TRACE", "Clearing %d output mappings from configuration",
             config->mapping_count);
  memset(config->mappings, 0, sizeof(config->mappings));
  config->mapping_count = 0;

  memset(config->default_image, 0, sizeof(config->default_image));

  chroma_log("DEBUG", "Freed configuration");
}

// Get image path for specific output
const char *chroma_config_get_image_for_output(chroma_config_t *config,
                                               const char *output_name) {
  if (!config || !output_name) {
    return NULL;
  }

  // Look for specific output mapping
  for (int i = 0; i < config->mapping_count; i++) {
    if (strcmp(config->mappings[i].output_name, output_name) == 0) {
      chroma_log("DEBUG", "Found specific mapping for output %s: %s",
                 output_name, config->mappings[i].image_path);
      return config->mappings[i].image_path;
    }
  }

  // Return default image if no specific mapping found
  if (strlen(config->default_image) > 0) {
    chroma_log("DEBUG", "Using default image for output %s: %s", output_name,
               config->default_image);
    return config->default_image;
  }

  chroma_log("WARN", "No image configured for output: %s", output_name);
  return NULL;
}

// Get configuration mapping for output, including scale mode, filter
// quality, anchor, and custom anchor coordinates
int chroma_config_get_mapping_for_output(
    chroma_config_t *config, const char *output_name,
    chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality,
    chroma_anchor_t *anchor, float *anchor_x, float *anchor_y) {
  if (!config || !output_name || !scale_mode || !filter_quality || !anchor ||
      !anchor_x || !anchor_y) {
    return CHROMA_ERROR_INIT;
  }

  // Look for specific output mapping
  for (int i = 0; i < config->mapping_count; i++) {
    if (strcmp(config->mappings[i].output_name, output_name) == 0) {
      *scale_mode = config->mappings[i].scale_mode;
      *filter_quality = config->mappings[i].filter_quality;
      *anchor = config->mappings[i].anchor;
      *anchor_x = config->mappings[i].anchor_x;
      *anchor_y = config->mappings[i].anchor_y;
      chroma_log("DEBUG",
                 "Found specific mapping for output %s: scale=%s, filter=%s, "
                 "anchor=%s @ %.1f,%.1f",
                 output_name, scale_mode_to_string(*scale_mode),
                 filter_quality_to_string(*filter_quality),
                 anchor_to_string(*anchor), *anchor_x, *anchor_y);
      return CHROMA_OK;
    }
  }

  // Return defaults if no specific mapping found
  *scale_mode = config->default_scale_mode;
  *filter_quality = config->default_filter_quality;
  *anchor = config->default_anchor;
  *anchor_x = config->default_anchor_x;
  *anchor_y = config->default_anchor_y;
  chroma_log("DEBUG",
             "Using defaults for output %s: scale=%s, filter=%s, anchor=%s @ "
             "%.1f,%.1f",
             output_name, scale_mode_to_string(*scale_mode),
             filter_quality_to_string(*filter_quality),
             anchor_to_string(*anchor), *anchor_x, *anchor_y);
  return CHROMA_OK;
}

// Print current configuration for debugging
void chroma_config_print(const chroma_config_t *config) {
  if (!config) {
    return;
  }

  chroma_log("INFO", "=== Configuration ===");
  chroma_log("INFO", "Default image: %s", config->default_image);
  chroma_log("INFO", "Daemon mode: %s", config->daemon_mode ? "true" : "false");
  chroma_log("INFO", "Default scale mode: %s",
             scale_mode_to_string(config->default_scale_mode));
  chroma_log("INFO", "Default filter quality: %s",
             filter_quality_to_string(config->default_filter_quality));
  chroma_log("INFO", "Downsampling: %s",
             config->enable_downsampling ? "enabled" : "disabled");
  if (config->enable_downsampling) {
    chroma_log("INFO", "Max output size: %dx%d", config->max_output_width,
               config->max_output_height);
    chroma_log("INFO", "Min scale factor: %.2f", config->min_scale_factor);
  }
  chroma_log("INFO", "Output mappings: %d", config->mapping_count);

  for (int i = 0; i < config->mapping_count; i++) {
    chroma_log("INFO", "  %s -> %s (scale: %s, filter: %s)",
               config->mappings[i].output_name, config->mappings[i].image_path,
               scale_mode_to_string(config->mappings[i].scale_mode),
               filter_quality_to_string(config->mappings[i].filter_quality));
    chroma_log(
        "TRACE",
        "  Mapping %d: output='%s', image='%s', scale='%s', filter='%s', "
        "path_exists=%s",
        i, config->mappings[i].output_name, config->mappings[i].image_path,
        scale_mode_to_string(config->mappings[i].scale_mode),
        filter_quality_to_string(config->mappings[i].filter_quality),
        chroma_path_exists(config->mappings[i].image_path) ? "yes" : "no");
  }
  chroma_log("INFO", "====================");
}
